From 7e063b7c95d28d86ac54ce99f2c0c87a95c4a088 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Tue, 26 Jun 2012 21:56:10 -0700 Subject: [PATCH 01/86] - fixed minor typo in description - dramatically simplified init method - removed size from kwargs so it doesn't propogate into options --- kivy/core/text/__init__.py | 91 ++++++++++++-------------------------- 1 file changed, 29 insertions(+), 62 deletions(-) diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index 887599109..8345dd1ec 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -6,8 +6,8 @@ Abstraction of text creation. Depending of the selected backend, the text rendering can be more or less accurate. .. versionadded:: - Starting to 1.0.7, the :class:`LabelBase` don't generate any texture is the - text have a width <= 1. + Starting to 1.0.7, the :class:`LabelBase` doesn't generate any texture if + the text have a width <= 1. ''' __all__ = ('LabelBase', 'Label') @@ -83,79 +83,46 @@ class LabelBase(object): _fonts_cache = {} def __init__(self, **kwargs): - if 'font_size' not in kwargs: - kwargs['font_size'] = 12 - if 'font_name' not in kwargs: - kwargs['font_name'] = DEFAULT_FONT - if 'bold' not in kwargs: - kwargs['bold'] = False - if 'italic' not in kwargs: - kwargs['italic'] = False - if 'halign' not in kwargs: - kwargs['halign'] = 'left' - if 'valign' not in kwargs: - kwargs['valign'] = 'bottom' - if 'padding_x' not in kwargs: - kwargs['padding_x'] = None - if 'padding_y' not in kwargs: - kwargs['padding_y'] = None - if 'shorten' not in kwargs: - kwargs['shorten'] = False - if 'mipmap' not in kwargs: - kwargs['mipmap'] = False - if 'color' not in kwargs: - kwargs['color'] = (1, 1, 1, 1) + kwargs.setdefault('font_size', 12) + kwargs.setdefault('font_name', DEFAULT_FONT) + kwargs.setdefault('bold', False) + kwargs.setdefault('italic', False) + kwargs.setdefault('halign', 'left') + kwargs.setdefault('valign', 'bottom') + kwargs.setdefault('shorten', False) + kwargs.setdefault('mipmap', False) + kwargs.setdefault('color', (1, 1, 1, 1)) + if 'padding' not in kwargs: - kwargs['padding'] = padding = None + kwargs['padding'] = (0.0, 0.0) else: - padding = kwargs['padding'] + kwargs['padding'] = float(kwargs['padding']) - tp_padding = type(padding) - padding_x = padding_y = None - if 'padding_x' in kwargs: - padding_x = kwargs['padding_x'] - if 'padding_y' in kwargs: - padding_y = kwargs['padding_y'] - if not padding_x: - if tp_padding is tuple or tp_padding is list: - kwargs['padding_x'] = padding_x = float(padding[0]) - elif padding is not None: - kwargs['padding_x'] = padding_x = float(padding) - else: - kwargs['padding_x'] = padding_x = 0 - if not padding_y: - if tp_padding is tuple or tp_padding is list: - kwargs['padding_y'] = float(padding[1]) - elif padding is not None: - kwargs['padding_y'] = float(padding) - else: - kwargs['padding_y'] = 0 + kwargs.setdefault('padding_x', kwargs['padding'][0]) + kwargs.setdefault('padding_y', kwargs['padding'][-1]) - if 'text_size' in kwargs: - ts = kwargs['text_size'] - elif 'size' in kwargs: - ts = kwargs['size'] + if 'text' not in kwargs: + self._text = u'' else: - ts = (None, None) + self._text = unicode(kwargs['text']) - uw = ts[0] - if uw is not None: - self._text_size = uw - padding_x * 2, ts[1] + if 'size' in kwargs: + kwargs['text_size'] = kwargs['size'] + del kwargs['size'] else: - self._text_size = ts + kwargs.setdefault('text_size', (None, None)) - super(LabelBase, self).__init__() + if kwargs['text_size'][0] is not None: + self._text_size = (kwargs['text_size'][0] - kwargs['padding_x'] * 2, + kwargs['text_size'][1]) + else: + self._text_size = kwargs['text_size'] - self._text = None - self._internal_height = 0 + self._internal_height = 0.0 self.options = kwargs self.texture = None self.resolve_font_name() - if 'text' in kwargs: - self.text = kwargs['text'] - else: - self.text = '' @staticmethod def register(name, fn_regular, fn_italic=None, fn_bold=None, From f9443628e0ebe97ed2116d32ea3a98f7494fc53a Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Tue, 26 Jun 2012 22:19:37 -0700 Subject: [PATCH 02/86] - simplified font_name_r code by taking advantage of the bitwise operator --- kivy/core/text/__init__.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index 8345dd1ec..4b3078d2e 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -52,7 +52,7 @@ class LabelBase(object): Activate "bold" text style `italic`: bool, default to False Activate "italic" text style - `text_size`: list, default to (None, None) + `text_size`: tuple, default to (None, None) Add constraint to render the text (inside a bounding box) If no size is given, the label size will be set to the text size. `padding`: int, default to None @@ -175,17 +175,13 @@ class LabelBase(object): # is the font is registered ? if fontname in fonts: # return the prefered font for the current bold/italic combinaison - bold = options['bold'] - italic = options['italic'] - font = fonts[fontname] - if not bold and not italic: - options['font_name_r'] = font[FONT_REGULAR] - elif bold and italic: - options['font_name_r'] = font[FONT_BOLDITALIC] - elif bold: - options['font_name_r'] = font[FONT_BOLD] + bold = int(options['bold']) + if options['italic']: + italic = FONT_ITALIC else: - options['font_name'] = font[FONT_ITALIC] + italic = FONT_REGULAR + + options['font_name_r'] = fonts[fontname][bold|italic] elif fontname in fontscache: options['font_name_r'] = fontscache[fontname] From ec865510a2849e24e52cb436570c78d691e421d7 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Tue, 26 Jun 2012 22:27:21 -0700 Subject: [PATCH 03/86] - minor formatting improvement --- kivy/core/text/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index 4b3078d2e..a68a40319 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -181,7 +181,7 @@ class LabelBase(object): else: italic = FONT_REGULAR - options['font_name_r'] = fonts[fontname][bold|italic] + options['font_name_r'] = fonts[fontname][bold | italic] elif fontname in fontscache: options['font_name_r'] = fontscache[fontname] From f7fdb42e7f2b2a32d43d40e3779d30db971b96a2 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Tue, 26 Jun 2012 22:38:59 -0700 Subject: [PATCH 04/86] - simplified register method --- kivy/core/text/__init__.py | 40 +++++++++++++++----------------------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index a68a40319..86969190e 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -131,7 +131,7 @@ class LabelBase(object): .. versionadded:: 1.1.0 - If you're using directly a ttf, you might not be able to use bold/italic + If you're using a ttf directly, you might not be able to use bold/italic of the ttf version. If the font is delivered with different version of it (one regular, one italic and one bold), then you need to register it and use the alias instead. @@ -140,29 +140,21 @@ class LabelBase(object): :func:`kivy.resources.resource_find`. If fn_italic/fn_bold are None, fn_regular will be used instead. ''' - _fn_regular = resource_find(fn_regular) - if _fn_regular is None: - raise IOError('File %r not found' % fn_regular) - if fn_italic is None: - _fn_italic = _fn_regular - else: - _fn_italic = resource_find(fn_italic) - if _fn_italic is None: - raise IOError('File %r not found' % fn_italic) - if fn_bold is None: - _fn_bold = _fn_regular - else: - _fn_bold = resource_find(fn_bold) - if _fn_bold is None: - raise IOError('File %r not found' % fn_bold) - if fn_bolditalic is None: - _fn_bolditalic = _fn_regular - else: - _fn_bolditalic = resource_find(fn_bolditalic) - if _fn_bolditalic is None: - raise IOError('Label: File %r not found' % fn_bolditalic) - LabelBase._fonts[name] = (_fn_regular, _fn_italic, _fn_bold, - _fn_bolditalic) + + fonts = [] + + for font_type in fn_regular, fn_italic, fn_bold, fn_bolditalic: + if font_type is not None: + font = resource_find(font_type) + + if font is None: + raise IOError('File {0}s not found'.format(font_type)) + else: + fonts.append(font) + else: + fonts.append(fonts[-1]) # add regular font to list again + + LabelBase._fonts[name] = tuple(fonts) def resolve_font_name(self): options = self.options From 1cdc071ca0f98f7017d93588c58aa112d7952bb1 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Tue, 26 Jun 2012 22:52:02 -0700 Subject: [PATCH 05/86] - refactored a bit more --- kivy/core/text/__init__.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index 86969190e..299473502 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -157,37 +157,31 @@ class LabelBase(object): LabelBase._fonts[name] = tuple(fonts) def resolve_font_name(self): - options = self.options - if 'font_name' not in options: - return - fontname = options['font_name'] - fonts = self._fonts + fontname = self.options['font_name'] fontscache = self._fonts_cache # is the font is registered ? - if fontname in fonts: + if fontname in self._fonts: # return the prefered font for the current bold/italic combinaison - bold = int(options['bold']) - if options['italic']: + bold = int(self.options['bold']) + if self.options['italic']: italic = FONT_ITALIC else: italic = FONT_REGULAR - options['font_name_r'] = fonts[fontname][bold | italic] + self.options['font_name_r'] = self._fonts[fontname][bold | italic] elif fontname in fontscache: - options['font_name_r'] = fontscache[fontname] + self.options['font_name_r'] = fontscache[fontname] else: filename = resource_find(fontname) if filename is None: # XXX for compatibility, check directly in the data dir filename = os.path.join(kivy_data_dir, fontname) if not os.path.exists(filename): - filename = None - if filename is None: - raise IOError('Label: File %r not found' % fontname) + raise IOError('Label: File %r not found' % fontname) fontscache[fontname] = filename - options['font_name_r'] = filename + self.options['font_name_r'] = filename def get_extents(self, text): '''Return a tuple with (width, height) for a text.''' From 26ba793621d02785b1e76c07d7070089bd4531d3 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Wed, 27 Jun 2012 00:33:56 -0700 Subject: [PATCH 06/86] - shortened (ha!) the shorten method - no longer uses a while loop - results are more symmetrical --- kivy/core/text/__init__.py | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index 299473502..821b47764 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -199,24 +199,13 @@ class LabelBase(object): def shorten(self, text): # Just a tiny shortcut textwidth = lambda txt: self.get_extents(txt)[0] - mid = len(text)/2 - begin = text[:mid].strip() - end = text[mid:].strip() - steps = 1 - middle = '...' - width = textwidth(begin+end) + textwidth(middle) - last_width = width - while width > self.text_size[0]: - begin = text[:mid - steps].strip() - end = text[mid + steps:].strip() - steps += 1 - width = textwidth(begin+end) + textwidth(middle) - if width == last_width: - # No more shortening possible. This is the best we can - # do. :-( -- Prevent infinite while loop. - break - last_width = width - return begin + middle + end + + letters = text + '...' + letter_width = textwidth(letters) // len(letters) + max_letters = self.text_size[0] // letter_width + segment = (max_letters // 2) - 3 + + return text[:segment] + '...' + text[-segment:] def render(self, real=False): '''Return a tuple(width, height) to create the image From ba7e7227f8f53427f54926f5ba0593e63ba48fae Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Wed, 27 Jun 2012 11:14:19 -0700 Subject: [PATCH 07/86] - attempting to speed up label creation (after slowing it down :-( ) --- kivy/core/text/__init__.py | 56 ++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index 821b47764..bea2c2619 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -82,45 +82,47 @@ class LabelBase(object): _fonts_cache = {} - def __init__(self, **kwargs): - kwargs.setdefault('font_size', 12) - kwargs.setdefault('font_name', DEFAULT_FONT) - kwargs.setdefault('bold', False) - kwargs.setdefault('italic', False) - kwargs.setdefault('halign', 'left') - kwargs.setdefault('valign', 'bottom') - kwargs.setdefault('shorten', False) - kwargs.setdefault('mipmap', False) - kwargs.setdefault('color', (1, 1, 1, 1)) + def __init__(self, text='', font_size=12, font_name=DEFAULT_FONT, + bold=False, italic=False, halign='left', valign='bottom', + shorten=False, text_size=None, mipmap=False, color=None, padding=None, + **kwargs): - if 'padding' not in kwargs: - kwargs['padding'] = (0.0, 0.0) + options = {'text': text, 'font_size': font_size, + 'font_name': font_name, 'bold': bold, 'italic': italic, + 'halign': halign, 'valign': valign, 'shorten': shorten, + 'mipmap': mipmap} + + if color is None: + options['color'] = (1, 1, 1, 1) else: - kwargs['padding'] = float(kwargs['padding']) + options['color'] = color - kwargs.setdefault('padding_x', kwargs['padding'][0]) - kwargs.setdefault('padding_y', kwargs['padding'][-1]) - - if 'text' not in kwargs: - self._text = u'' + if padding is None: + options['padding'] = (0.0, 0.0) else: - self._text = unicode(kwargs['text']) + options['padding'] = float(padding), float(padding) + + options['padding_x'], options['padding_y'] = options['padding'] if 'size' in kwargs: - kwargs['text_size'] = kwargs['size'] - del kwargs['size'] + options['text_size'] = kwargs['size'] else: - kwargs.setdefault('text_size', (None, None)) + if text_size is None: + options['text_size'] = (None, None) + else: + options['text_size'] = text_size - if kwargs['text_size'][0] is not None: - self._text_size = (kwargs['text_size'][0] - kwargs['padding_x'] * 2, - kwargs['text_size'][1]) + if options['text_size'][0] is not None: + self._text_size = ( + options['text_size'][0] - options['padding_x'] * 2, + options['text_size'][1]) else: - self._text_size = kwargs['text_size'] + self._text_size = options['text_size'] + self._text = options['text'] self._internal_height = 0.0 - self.options = kwargs + self.options = options self.texture = None self.resolve_font_name() From 1dd081967ee1557720a11231cf1ffacbb5725d63 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Wed, 27 Jun 2012 11:33:50 -0700 Subject: [PATCH 08/86] - more attempts at optimization without --- kivy/core/text/__init__.py | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index bea2c2619..61504126c 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -55,11 +55,11 @@ class LabelBase(object): `text_size`: tuple, default to (None, None) Add constraint to render the text (inside a bounding box) If no size is given, the label size will be set to the text size. - `padding`: int, default to None - If it's a integer, it will set padding_x and padding_y - `padding_x`: int, default to 0 + `padding`: float, default to None + If it's a float, it will set padding_x and padding_y + `padding_x`: float, default to 0.0 Left/right padding - `padding_y`: int, default to 0 + `padding_y`: float, default to 0.0 Top/bottom padding `halign`: str, default to "left" Horizontal text alignement inside bounding box @@ -84,7 +84,7 @@ class LabelBase(object): def __init__(self, text='', font_size=12, font_name=DEFAULT_FONT, bold=False, italic=False, halign='left', valign='bottom', - shorten=False, text_size=None, mipmap=False, color=None, padding=None, + shorten=False, text_size=None, mipmap=False, color=None, **kwargs): options = {'text': text, 'font_size': font_size, @@ -92,17 +92,10 @@ class LabelBase(object): 'halign': halign, 'valign': valign, 'shorten': shorten, 'mipmap': mipmap} - if color is None: - options['color'] = (1, 1, 1, 1) - else: - options['color'] = color - - if padding is None: - options['padding'] = (0.0, 0.0) - else: - options['padding'] = float(padding), float(padding) - - options['padding_x'], options['padding_y'] = options['padding'] + options['color'] = color or (1, 1, 1, 1) + options['padding'] = kwargs.get('padding', 0) + options['padding_x'] = kwargs.get('padding_x', options['padding']) + options['padding_y'] = kwargs.get('padding_x', options['padding']) if 'size' in kwargs: options['text_size'] = kwargs['size'] From b7595649b24504bbe2832ca33447dc5220ae6e04 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Wed, 27 Jun 2012 13:34:57 -0700 Subject: [PATCH 09/86] - added margin argument to use in calculations rather than arbitrary value - changed clipping strategy when resulting string is too short - stripped both ends of the segment --- kivy/core/text/__init__.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index 61504126c..132f12383 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -191,16 +191,21 @@ class LabelBase(object): def _render_end(self): pass - def shorten(self, text): + def shorten(self, text, margin=2): # Just a tiny shortcut textwidth = lambda txt: self.get_extents(txt)[0] letters = text + '...' letter_width = textwidth(letters) // len(letters) max_letters = self.text_size[0] // letter_width - segment = (max_letters // 2) - 3 + segment = (max_letters // 2) - return text[:segment] + '...' + text[-segment:] + if segment - margin > 5: + segment -= margin + return text[:segment].strip() + '...' + text[-segment:].strip() + else: + segment = max_letters - 3 + return text[:segment].strip() + '...' def render(self, real=False): '''Return a tuple(width, height) to create the image From aae0287857beac0fd9aed32ee5b777f2630ed140 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Wed, 27 Jun 2012 17:31:00 -0700 Subject: [PATCH 10/86] - reverted dot access back to aliased variables --- kivy/core/text/__init__.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index 132f12383..326da6368 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -113,7 +113,7 @@ class LabelBase(object): self._text_size = options['text_size'] self._text = options['text'] - self._internal_height = 0.0 + self._internal_height = 0 self.options = options self.texture = None @@ -152,22 +152,24 @@ class LabelBase(object): LabelBase._fonts[name] = tuple(fonts) def resolve_font_name(self): + options = self.options fontname = self.options['font_name'] + fonts = self._fonts fontscache = self._fonts_cache # is the font is registered ? - if fontname in self._fonts: + if fontname in fonts: # return the prefered font for the current bold/italic combinaison - bold = int(self.options['bold']) - if self.options['italic']: + bold = int(options['bold']) + if options['italic']: italic = FONT_ITALIC else: italic = FONT_REGULAR - self.options['font_name_r'] = self._fonts[fontname][bold | italic] + options['font_name_r'] = fonts[fontname][bold | italic] elif fontname in fontscache: - self.options['font_name_r'] = fontscache[fontname] + options['font_name_r'] = fontscache[fontname] else: filename = resource_find(fontname) if filename is None: @@ -176,7 +178,7 @@ class LabelBase(object): if not os.path.exists(filename): raise IOError('Label: File %r not found' % fontname) fontscache[fontname] = filename - self.options['font_name_r'] = filename + options['font_name_r'] = filename def get_extents(self, text): '''Return a tuple with (width, height) for a text.''' @@ -202,10 +204,11 @@ class LabelBase(object): if segment - margin > 5: segment -= margin - return text[:segment].strip() + '...' + text[-segment:].strip() + return '{0}...{1}'.format(text[:segment].strip(), + text[-segment:].strip()) else: segment = max_letters - 3 - return text[:segment].strip() + '...' + return '{0}...'.format(text[:segment].strip()) def render(self, real=False): '''Return a tuple(width, height) to create the image From fec3f1524cdb3f788dce8cf20108ee0eb6e73d2d Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Wed, 27 Jun 2012 17:48:08 -0700 Subject: [PATCH 11/86] - stupid typo (thanks tito) --- kivy/core/text/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index 326da6368..934d2b598 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -95,7 +95,7 @@ class LabelBase(object): options['color'] = color or (1, 1, 1, 1) options['padding'] = kwargs.get('padding', 0) options['padding_x'] = kwargs.get('padding_x', options['padding']) - options['padding_y'] = kwargs.get('padding_x', options['padding']) + options['padding_y'] = kwargs.get('padding_y', options['padding']) if 'size' in kwargs: options['text_size'] = kwargs['size'] From bc813e48f2547b85b712119620d083e4f220b13e Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Wed, 27 Jun 2012 17:59:45 -0700 Subject: [PATCH 12/86] final (?) optimizations --- kivy/core/text/__init__.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index 934d2b598..694367fca 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -105,10 +105,11 @@ class LabelBase(object): else: options['text_size'] = text_size - if options['text_size'][0] is not None: + text_width, text_height = options['text_size'] + if text_width is not None: self._text_size = ( - options['text_size'][0] - options['padding_x'] * 2, - options['text_size'][1]) + text_width - options['padding_x'] * 2, + text_height) else: self._text_size = options['text_size'] @@ -207,7 +208,7 @@ class LabelBase(object): return '{0}...{1}'.format(text[:segment].strip(), text[-segment:].strip()) else: - segment = max_letters - 3 + segment = max_letters - 3 # length of '...' return '{0}...'.format(text[:segment].strip()) def render(self, real=False): From 60197a9fb32b98e569ae1481379d650075a7490c Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Sat, 7 Jul 2012 13:38:06 -0700 Subject: [PATCH 13/86] - had italic and bold flipped. markup works now --- kivy/core/text/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index 694367fca..7b07d1645 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -161,13 +161,13 @@ class LabelBase(object): # is the font is registered ? if fontname in fonts: # return the prefered font for the current bold/italic combinaison - bold = int(options['bold']) - if options['italic']: - italic = FONT_ITALIC + italic = int(options['italic']) + if options['bold']: + bold = FONT_BOLD else: - italic = FONT_REGULAR + bold = FONT_REGULAR - options['font_name_r'] = fonts[fontname][bold | italic] + options['font_name_r'] = fonts[fontname][italic | bold] elif fontname in fontscache: options['font_name_r'] = fontscache[fontname] From 1f630b40b7f980b8dba4f5e9c72cfe15e4d10625 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Sun, 15 Jul 2012 11:35:48 -0700 Subject: [PATCH 14/86] - made sure size is always evaluated as an integer --- kivy/core/text/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index 7b07d1645..b9bc94882 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -450,8 +450,8 @@ class LabelBase(object): def _get_text_size(self): return self._text_size - def _set_text_size(self, x): - self._text_size = x + def _set_text_size(self, value): + self._text_size = tuple([x if x is None else int(x) for x in value]) text_size = property(_get_text_size, _set_text_size, doc='''Get/set the (width, height) of the contrained rendering box''') From a8e8b5a1ce5c818331ccc327aa71e3fb69bd9d68 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Sun, 15 Jul 2012 11:46:07 -0700 Subject: [PATCH 15/86] - reverted old behaviour; only changing to int when calculating display width --- kivy/core/text/__init__.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index b9bc94882..90403ecc2 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -197,10 +197,14 @@ class LabelBase(object): def shorten(self, text, margin=2): # Just a tiny shortcut textwidth = lambda txt: self.get_extents(txt)[0] + if self.text_size[0] is None: + width = 0 + else: + width = int(self.text_size[0]) letters = text + '...' letter_width = textwidth(letters) // len(letters) - max_letters = self.text_size[0] // letter_width + max_letters = width // letter_width segment = (max_letters // 2) if segment - margin > 5: @@ -450,8 +454,8 @@ class LabelBase(object): def _get_text_size(self): return self._text_size - def _set_text_size(self, value): - self._text_size = tuple([x if x is None else int(x) for x in value]) + def _set_text_size(self, x): + self._text_size = x text_size = property(_get_text_size, _set_text_size, doc='''Get/set the (width, height) of the contrained rendering box''') From e49a29f1e9b3f137bc4570b1cfad69022e0bf448 Mon Sep 17 00:00:00 2001 From: Qua-non Date: Mon, 16 Jul 2012 02:00:50 +0530 Subject: [PATCH 16/86] UIX: Widget: Warn and skip addition if widget already has parent. Along with fixes in TabbedPanel and Bubble for issues due to this warning. --- kivy/uix/bubble.py | 5 +++++ kivy/uix/tabbedpanel.py | 6 ++++++ kivy/uix/widget.py | 8 ++++++++ 3 files changed, 19 insertions(+) diff --git a/kivy/uix/bubble.py b/kivy/uix/bubble.py index 3fb6cc084..d76907758 100644 --- a/kivy/uix/bubble.py +++ b/kivy/uix/bubble.py @@ -157,6 +157,7 @@ class Bubble(GridLayout): color=self.background_color) self.content = content = BubbleContent(parent=self) super(Bubble, self).__init__(**kwargs) + content.parent = None self.add_widget(content) self.on_arrow_pos() @@ -226,6 +227,10 @@ class Bubble(GridLayout): self_arrow_img.height = self_arrow_img.texture_size[1] widget_list = [] arrow_list = [] + parent = self_arrow_img.parent + if parent: + parent.remove_widget(self_arrow_img) + if self_arrow_pos[0] == 'b' or self_arrow_pos[0] == 't': self.cols = 1 self.rows = 2 diff --git a/kivy/uix/tabbedpanel.py b/kivy/uix/tabbedpanel.py index c6faef39c..e39d9fd9f 100644 --- a/kivy/uix/tabbedpanel.py +++ b/kivy/uix/tabbedpanel.py @@ -393,6 +393,9 @@ class TabbedPanel(GridLayout): content = self.content if content is None: return + parent = widget.parent + if widget.parent: + parent.remove_widget(widget) if widget == content or widget == self._tab_layout: super(TabbedPanel, self).add_widget(widget, index) elif isinstance(widget, TabbedPanelHeader): @@ -491,6 +494,9 @@ class TabbedPanel(GridLayout): tab_layout.clear_widgets() scrl_v = ScrollView(size_hint=(None, 1)) tabs = self._tab_strip + parent = tabs.parent + if parent: + parent.remove_widget(tabs) scrl_v.add_widget(tabs) scrl_v.pos = (0, 0) self_update_scrollview = self._update_scrollview diff --git a/kivy/uix/widget.py b/kivy/uix/widget.py index 8c39a94e0..5042c2100 100644 --- a/kivy/uix/widget.py +++ b/kivy/uix/widget.py @@ -65,6 +65,7 @@ from kivy.properties import NumericProperty, StringProperty, \ from kivy.graphics import Canvas from kivy.base import EventLoop from kivy.lang import Builder +from kivy.logger import Logger class WidgetException(Exception): @@ -227,6 +228,13 @@ class Widget(EventDispatcher): if not isinstance(widget, Widget): raise WidgetException( 'add_widget() can be used only with Widget classes.') + parent = widget.parent + # check if widget is already a child of another widget + if parent: + Logger.warning(''.join(('Cannot add Widget ', str(widget),\ + ' It already has a parent ', str(parent), + ' Skipping addition'))) + return widget.parent = self if index == 0 or len(self.children) == 0: self.children.insert(0, widget) From 286d0172fc3bae8fc6f29c0bbd3755a4f81f8416 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Sun, 15 Jul 2012 17:11:54 +0200 Subject: [PATCH 17/86] screenmanager use screen.transition_progress instead of value|alpha for consistency --- kivy/uix/screenmanager.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/kivy/uix/screenmanager.py b/kivy/uix/screenmanager.py index 2de9a7066..1d5ecf39b 100644 --- a/kivy/uix/screenmanager.py +++ b/kivy/uix/screenmanager.py @@ -151,7 +151,7 @@ class Screen(RelativeLayout): None, read-only. ''' - transition_alpha = NumericProperty(0.) + transition_progress = NumericProperty(0.) '''Value that represent the completion of the current transition, if any is occuring. @@ -159,7 +159,7 @@ class Screen(RelativeLayout): to 1. If you want to know if it's an entering or leaving animation, check the :data:`transition_state` - :data:`transition_alpha` is a :class:`~kivy.properties.NumericProperty`, + :data:`transition_progress` is a :class:`~kivy.properties.NumericProperty`, default to 0. ''' @@ -241,9 +241,9 @@ class TransitionBase(EventDispatcher): on_complete=self._on_complete) self.add_screen(self.screen_in) - self.screen_in.transition_value = 0. + self.screen_in.transition_progress = 0. self.screen_in.transition_mode = 'in' - self.screen_out.transition_value = 0. + self.screen_out.transition_progress = 0. self.screen_out.transition_mode = 'out' self._anim.start(self) @@ -275,10 +275,10 @@ class TransitionBase(EventDispatcher): pass def _on_progress(self, *l): - alpha = l[-1] - self.screen_in.transition_value = alpha - self.screen_out.transition_value = 1. - alpha - self.dispatch('on_progress', alpha) + progress = l[-1] + self.screen_in.transition_progress = progress + self.screen_out.transition_progress = 1. - progress + self.dispatch('on_progress', progress) def _on_complete(self, *l): self.dispatch('on_complete') From 153ffacf7c397b6815c7a2317484c6897f78d51f Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Tue, 17 Jul 2012 10:52:38 -0700 Subject: [PATCH 18/86] - now possible to set a window's size at runtime (respects rotation) --- kivy/core/window/__init__.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/kivy/core/window/__init__.py b/kivy/core/window/__init__.py index 201f5e360..cee1d3e53 100755 --- a/kivy/core/window/__init__.py +++ b/kivy/core/window/__init__.py @@ -250,17 +250,22 @@ class WindowBase(EventDispatcher): def _get_size(self): r = self._rotation w, h = self._size - if r == 0 or r == 180: + if r in (0, 180): return w, h return h, w def _set_size(self, size): - if super(WindowBase, self)._set_size(size): - Logger.debug('Window: Resize window to %s' % str(self.size)) + if self._size != size: + r = self._rotation + if r in (0, 180): + self._size = size + else: + self._size = size[1], size[0] + self.dispatch('on_resize', *size) return True - return False - + else: + return False size = AliasProperty(_get_size, _set_size) '''Get the rotated size of the window. If :data:`rotation` is set, then the size will change to reflect the rotation. From 4208be2f666b15a492a35c4722f879c040b2f8ca Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Wed, 18 Jul 2012 17:40:13 +0200 Subject: [PATCH 19/86] doc: fix event/parameters/fieldlist css --- doc/sources/.static/default.css | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/doc/sources/.static/default.css b/doc/sources/.static/default.css index ab16bab4c..a3b566cad 100644 --- a/doc/sources/.static/default.css +++ b/doc/sources/.static/default.css @@ -708,3 +708,22 @@ dl.api-level dt { float: left; margin-right: 22px; } + +/** Fix list within dt + */ +table.field-list dt { + margin: 0px; + background-color: #eeeeee; +} + +table.field-list dl { + margin-top: 0px; +} +table.field-list td.field-body { + padding-top: 0px; +} +table.field-list th.field-name { + min-width: 100px; +} + + From 0a2e38dcc7f927625f2bcca466c2e73d45b5d394 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Wed, 18 Jul 2012 17:40:27 +0200 Subject: [PATCH 20/86] doc: fix clipboard doc, and remove personal comments --- kivy/core/clipboard/__init__.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/kivy/core/clipboard/__init__.py b/kivy/core/clipboard/__init__.py index 3f80d1a13..ac9954211 100644 --- a/kivy/core/clipboard/__init__.py +++ b/kivy/core/clipboard/__init__.py @@ -5,22 +5,22 @@ Clipboard Core class for accessing to the Clipboard. If we are not able to access to the system clipboard, a fake one will be used. -Usage example (i have copied 'Hello World' somewhere else):: +Usage example:: >>> from kivy.core.clipboard import Clipboard >>> Clipboard.get_types() ['TIMESTAMP', 'TARGETS', 'MULTIPLE', 'SAVE_TARGETS', 'UTF8_STRING', 'COMPOUND_TEXT', 'TEXT', 'STRING', 'text/plain;charset=utf-8', 'text/plain'] - >>> Clipboard.get('TEXT') - 'Hello World' - >>> Clipboard.put('Great', 'UTF8_STRING') - >>> Clipboard.get_types() - ['UTF8_STRING'] - >>> Clipboard.get('UTF8_STRING') - 'Great' + >>> Clipboard.get('TEXT') + 'Hello World' + >>> Clipboard.put('Great', 'UTF8_STRING') + >>> Clipboard.get_types() + ['UTF8_STRING'] + >>> Clipboard.get('UTF8_STRING') + 'Great' -Note that the main implementation rely on Pygame, and works great with +.. note:: the main implementation rely on Pygame, and works great with text/string. Anything else might not work the same on all platform. ''' From 66a87983b7fff67b7754b735b076a70008bad027 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Wed, 18 Jul 2012 17:40:42 +0200 Subject: [PATCH 21/86] doc: add little doc for spelling core provider --- kivy/core/spelling/__init__.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/kivy/core/spelling/__init__.py b/kivy/core/spelling/__init__.py index 1942e2918..b3ba9d003 100644 --- a/kivy/core/spelling/__init__.py +++ b/kivy/core/spelling/__init__.py @@ -5,6 +5,21 @@ Spelling Provide abstracted access to a range of spellchecking backends. Also provides word suggestions. The API is inspired by enchant, but other backends can be added that implement the same API. + +Spelling currently require `python-enchant` for all platform, except OSX, where +a native implementation exist. + +:: + + >>> from kivy.core.spelling import Spelling + >>> s = Spelling() + >>> s.list_languages() + ['en', 'en_CA', 'en_GB', 'en_US'] + >>> s.select_language('en_US') + >>> s.check('helo') + [u'hole', u'help', u'helot', u'hello', u'halo', u'hero', u'hell', u'held', + u'helm', u'he-lo'] + ''' __all__ = ('Spelling', 'SpellingBase', 'NoSuchLangError', From 85f6b62fba2d33c1aed26bb47e183903d159777b Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Wed, 18 Jul 2012 17:52:17 +0200 Subject: [PATCH 22/86] doc: fix versionchanged syntax, message wasnt showed anymore --- doc/sources/guide/packaging-android.rst | 10 +++----- kivy/_event.pyx | 2 -- kivy/animation.py | 8 +++--- kivy/app.py | 1 - kivy/clock.py | 1 - kivy/config.py | 33 +++++++++++-------------- kivy/core/text/__init__.py | 7 +++--- kivy/core/window/__init__.py | 1 - kivy/graphics/stencil_instructions.pyx | 1 - kivy/network/urlrequest.py | 2 +- kivy/properties.pyx | 1 - kivy/uix/filechooser.py | 4 +-- kivy/uix/popup.py | 4 +-- kivy/uix/scatter.py | 1 - kivy/uix/widget.py | 1 - 15 files changed, 28 insertions(+), 49 deletions(-) diff --git a/doc/sources/guide/packaging-android.rst b/doc/sources/guide/packaging-android.rst index 56da5295e..270068bfc 100644 --- a/doc/sources/guide/packaging-android.rst +++ b/doc/sources/guide/packaging-android.rst @@ -4,13 +4,9 @@ Create a package for Android ============================ .. versionchanged:: 1.1.0 - - Starting from 1.1.0, we are not providing anymore a Kivy-XXX-android.zip. - We are using `python-for-android `_ - project. - - The whole packaging is explained at - `http://python-for-android.readthedocs.org/en/latest/index.html`_ + Kivy-XXX-android.zip is not provided anymore. We are using + `python-for-android `_ + (`doc `_) Packaging your application into APK ----------------------------------- diff --git a/kivy/_event.pyx b/kivy/_event.pyx index b6abf1dd6..8e1f57f2d 100644 --- a/kivy/_event.pyx +++ b/kivy/_event.pyx @@ -6,9 +6,7 @@ All objects that produce events in Kivy implement :class:`EventDispatcher`, providing a consistent interface for registering and manipulating event handlers. - .. versionchanged:: 1.0.9 - Properties discovering and methods have been moved from :class:`~kivy.uix.widget.Widget` to :class:`EventDispatcher` diff --git a/kivy/animation.py b/kivy/animation.py index ca50ce8bd..df728e1d6 100644 --- a/kivy/animation.py +++ b/kivy/animation.py @@ -69,10 +69,6 @@ from kivy.clock import Clock class Animation(EventDispatcher): '''Create an animation definition that can be used to animate a Widget - .. versionchanged:: 1.4.0 - - Added s/step parameter. - :Parameters: `duration` or `d`: float, default to 1. Duration of the animation, in seconds @@ -89,6 +85,10 @@ class Animation(EventDispatcher): Fired when the animation is completed or stopped on a widget `on_progress`: widget, progression Fired when the progression of the animation is changing + + .. versionchanged:: 1.4.0 + Added s/step parameter. + ''' _instances = set() diff --git a/kivy/app.py b/kivy/app.py index ae71a2c4a..d6cabb7de 100644 --- a/kivy/app.py +++ b/kivy/app.py @@ -408,7 +408,6 @@ class App(EventDispatcher): '''.. versionadded:: 1.0.7 .. versionchanged:: 1.4.0 - Customize the default path for iOS and Android platform. Add defaultpath parameter for desktop computer (not applicatable for iOS and Android.) diff --git a/kivy/clock.py b/kivy/clock.py index ae20832ec..e35a0cad8 100644 --- a/kivy/clock.py +++ b/kivy/clock.py @@ -353,7 +353,6 @@ class ClockBase(object): '''Schedule an event in seconds. .. versionchanged:: 1.0.5 - If the timeout is -1, the callback will be called before the next frame (at :func:`tick_draw`). diff --git a/kivy/config.py b/kivy/config.py index f5c046fa4..1c7280222 100644 --- a/kivy/config.py +++ b/kivy/config.py @@ -23,24 +23,6 @@ Change the configuration and save it:: Available configuration tokens ------------------------------ -.. versionchanged:: 1.0.8 - - * `scroll_timeout`, `scroll_distance` and `scroll_friction` have been added - * `list_friction`, `list_trigger_distance` and `list_friction_bound` have - been removed. - * `keyboard_type` and `keyboard_layout` have been removed from widget - * `keyboard_mode` and `keyboard_layout` have been added to kivy section - -.. versionchanged:: 1.1.0 - - * tuio is not listening by default anymore. - * windows icons are not copied to user directory anymore. You can still set - a new window icon by using ``window_icon`` config setting. - -.. versionchanged:: 1.2.0 - - * `resizable` has been added to graphics section - :kivy: `log_level`: (debug, info, warning, error, critical) @@ -164,6 +146,21 @@ Available configuration tokens Anything after the = will be passed to the module as arguments. Check the specific module's documentation for a list of accepted arguments. + +.. versionchanged:: 1.2.0 + `resizable` has been added to graphics section + +.. versionchanged:: 1.1.0 + tuio is not listening by default anymore. windows icons are not copied to + user directory anymore. You can still set a new window icon by using + ``window_icon`` config setting. + +.. versionchanged:: 1.0.8 + `scroll_timeout`, `scroll_distance` and `scroll_friction` have been added. + `list_friction`, `list_trigger_distance` and `list_friction_bound` have been + removed. `keyboard_type` and `keyboard_layout` have been removed from + widget. `keyboard_mode` and `keyboard_layout` have been added to kivy + section. ''' __all__ = ('Config', 'ConfigParser') diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index 887599109..390bd47e0 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -5,9 +5,9 @@ Text Abstraction of text creation. Depending of the selected backend, the text rendering can be more or less accurate. -.. versionadded:: - Starting to 1.0.7, the :class:`LabelBase` don't generate any texture is the - text have a width <= 1. +.. versionchanged:: 1.0.7 + The :class:`LabelBase` don't generate any texture is the text have a width + <= 1. ''' __all__ = ('LabelBase', 'Label') @@ -17,7 +17,6 @@ import os from kivy import kivy_data_dir from kivy.graphics.texture import Texture from kivy.core import core_select_lib -from kivy.utils import platform from kivy.resources import resource_find DEFAULT_FONT = 'DroidSans' diff --git a/kivy/core/window/__init__.py b/kivy/core/window/__init__.py index 201f5e360..380dcf468 100755 --- a/kivy/core/window/__init__.py +++ b/kivy/core/window/__init__.py @@ -883,7 +883,6 @@ class WindowBase(EventDispatcher): and if configuration allowed it, a VKeyboard instance. .. versionchanged:: 1.0.8 - `target` have been added, and must be the widget source that request the keyboard. If set, the widget must have one method named `on_keyboard_text`, that will be called from the vkeyboard. diff --git a/kivy/graphics/stencil_instructions.pyx b/kivy/graphics/stencil_instructions.pyx index e34a1ac86..092fe3146 100644 --- a/kivy/graphics/stencil_instructions.pyx +++ b/kivy/graphics/stencil_instructions.pyx @@ -5,7 +5,6 @@ Stencil instructions .. versionadded:: 1.0.4 .. versionchanged:: 1.3.0 - The stencil operation have been updated to resolve some issues appearing when nested. You **must** know have a StencilUnUse and repeat the same operation as you did after StencilPush. diff --git a/kivy/network/urlrequest.py b/kivy/network/urlrequest.py index f77a38614..9e144cfed 100644 --- a/kivy/network/urlrequest.py +++ b/kivy/network/urlrequest.py @@ -74,7 +74,7 @@ from kivy.clock import Clock class UrlRequest(Thread): '''Url request. See module documentation for usage. - .. versionchanged:: + .. versionchanged:: 1.0.10 Add `method` parameters :Parameters: diff --git a/kivy/properties.pyx b/kivy/properties.pyx index fbf95186d..3ad44534b 100644 --- a/kivy/properties.pyx +++ b/kivy/properties.pyx @@ -305,7 +305,6 @@ cdef class Property: '''Dispatch the value change to all observers .. versionchanged:: 1.1.0 - The method is now accessible from Python. This can be used to force the dispatch of the property, even if the diff --git a/kivy/uix/filechooser.py b/kivy/uix/filechooser.py index fb07a3663..40b708b55 100644 --- a/kivy/uix/filechooser.py +++ b/kivy/uix/filechooser.py @@ -10,10 +10,8 @@ FileChooser present. .. versionchanged:: 1.2.0 - In chooser template, the `controller` is not a direct reference anymore, but - a weak-reference. - You must update all the notation `root.controller.xxx` to + a weak-reference. You must update all the notation `root.controller.xxx` to `root.controller().xxx`. ''' diff --git a/kivy/uix/popup.py b/kivy/uix/popup.py index a5571c264..bd2c1ff0d 100644 --- a/kivy/uix/popup.py +++ b/kivy/uix/popup.py @@ -237,11 +237,9 @@ class Popup(FloatLayout): popup.dismiss(force=True) .. versionchanged:: 1.3.0 - When the popup is dismissed, it will be faded out, before removal from the parent. If you don't want animation, use: - - popup.dismiss(animation=False) + `popup.dismiss(animation=False)` ''' if self._window is None: diff --git a/kivy/uix/scatter.py b/kivy/uix/scatter.py index d50002ec9..a431b1fae 100644 --- a/kivy/uix/scatter.py +++ b/kivy/uix/scatter.py @@ -80,7 +80,6 @@ Behaviors --------- .. versionchanged:: 1.1.0 - If no control interactions are enabled, then touch handler will never return True. diff --git a/kivy/uix/widget.py b/kivy/uix/widget.py index 8c39a94e0..e0248e492 100644 --- a/kivy/uix/widget.py +++ b/kivy/uix/widget.py @@ -85,7 +85,6 @@ class Widget(EventDispatcher): Fired when an existing touch disappears .. versionchanged:: 1.0.9 - Everything related to event properties has been moved to :class:`~kivy.event.EventDispatcher`. Event properties can now be used in contructing a simple class, without subclassing :class:`Widget`. From 5eaf030992689329679507903a526c7055422cd3 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Thu, 19 Jul 2012 02:40:33 +0200 Subject: [PATCH 23/86] gl: try to fix reloading texture cache when atlas is used. Actually, no need to reload atlas objects, only the associated texture, and it's already done so... Just restore the texture cache "in case of". Refs #578 --- kivy/graphics/context.pyx | 17 +++++++++++++++-- kivy/graphics/texture.pyx | 3 --- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/kivy/graphics/context.pyx b/kivy/graphics/context.pyx index 011c5c614..fa469b351 100644 --- a/kivy/graphics/context.pyx +++ b/kivy/graphics/context.pyx @@ -122,11 +122,15 @@ cdef class Context: cdef Shader shader cdef Canvas canvas - Cache.remove('kv.atlas') Cache.remove('kv.image') - Cache.remove('kv.texture') Cache.remove('kv.shader') + # For texture cache, save the objects. We need to clean the cache as the + # others to prevent of using it during the reloading part. + # We'll restore the object later. + texture_objects = Cache._objects['kv.texture'] + Cache.remove('kv.texture') + start = time() Logger.info('Context: Reloading graphics data...') Logger.debug('Context: Collect and flush all garbage') @@ -143,6 +147,7 @@ cdef class Context: texture = item() if texture is None: continue + Logger.trace('Context: unset texture id %r' % texture) texture._id = -1 # First time, only reload base texture @@ -150,14 +155,22 @@ cdef class Context: texture = item() if texture is None or isinstance(texture, TextureRegion): continue + Logger.trace('Context: >> reload base texture %r' % texture) texture.reload() + Logger.trace('Context: << reload base texture %r' % texture) # Second time, update texture region id for item in l: texture = item() if texture is None or not isinstance(texture, TextureRegion): continue + Logger.trace('Context: >> reload region texture %r' % texture) texture.reload() + Logger.trace('Context: << reload region texture %r' % texture) + + # Restore texture cache + texture_objects.update(Cache._objects['kv.texture']) + Cache._objects['kv.texture'] = texture_objects Logger.debug('Context: Reload vbos') for item in self.l_vbo[:]: diff --git a/kivy/graphics/texture.pyx b/kivy/graphics/texture.pyx index 8af25b9b7..33042041b 100644 --- a/kivy/graphics/texture.pyx +++ b/kivy/graphics/texture.pyx @@ -184,11 +184,8 @@ include "config.pxi" include "common.pxi" include "opengl_utils_def.pxi" -from os import environ from array import array from kivy.weakmethod import WeakMethod -from kivy.logger import Logger -from kivy.cache import Cache from kivy.graphics.context cimport get_context from kivy.graphics.c_opengl cimport * From 60ba121e302d78ed3de7d5f233c94735e1599796 Mon Sep 17 00:00:00 2001 From: "gabriel.pettier" Date: Thu, 19 Jul 2012 22:54:44 +0200 Subject: [PATCH 24/86] closes #579 --- kivy/uix/floatlayout.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kivy/uix/floatlayout.py b/kivy/uix/floatlayout.py index c15d11779..61a5f1a55 100644 --- a/kivy/uix/floatlayout.py +++ b/kivy/uix/floatlayout.py @@ -95,10 +95,14 @@ class FloatLayout(Layout): c.x = x + value * w elif key == 'right': c.right = x + value * w + elif key == 'pos': + c.pos = x + value[0] * w, y + value[1] * h elif key == 'y': c.y = y + value * h elif key == 'top': c.top = y + value * h + elif key == 'center': + c.center = x + value[0] * w, y + value[1] * h elif key == 'center_x': c.center_x = x + value * w elif key == 'center_y': From b67ad45e40db8345a3a5275d0a5a648afd1f94d9 Mon Sep 17 00:00:00 2001 From: "gabriel.pettier" Date: Fri, 20 Jul 2012 01:30:34 +0200 Subject: [PATCH 25/86] merge callable_filechooser_filters --- kivy/uix/filechooser.py | 72 ++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 29 deletions(-) diff --git a/kivy/uix/filechooser.py b/kivy/uix/filechooser.py index 40b708b55..44a9c087e 100644 --- a/kivy/uix/filechooser.py +++ b/kivy/uix/filechooser.py @@ -6,12 +6,13 @@ FileChooser .. warning:: - This is experimental and subject to change as long as this warning notice is - present. + This is experimental and subject to change as long as this warning notice + is present. .. versionchanged:: 1.2.0 - In chooser template, the `controller` is not a direct reference anymore, but - a weak-reference. You must update all the notation `root.controller.xxx` to + In chooser template, the `controller` is not a direct reference anymore, + but a weak-reference. + You must update all the notation `root.controller.xxx` to `root.controller().xxx`. ''' @@ -138,19 +139,29 @@ class FileChooserController(FloatLayout): filters = ListProperty([]) ''':class:`~kivy.properties.ListProperty`, defaults to [], equal to '\*'. - The filters to be applied to the files in the directory, e.g. ['\*.png']. + The filters to be applied to the files in the directory. + The filters are not reset when the path changes. You need to do that - yourself if desired. You can use the following patterns: + yourself if desired. - ========== ================================= - Pattern Meaning - ========== ================================= - \* matches everything - ? matches any single character - [seq] matches any character in seq - [!seq] matches any character not in seq - ========== ================================= + There are two kinds of filters : + filename patterns : e.g. ['\*.png']. + You can use the following patterns: + + ========== ================================= + Pattern Meaning + ========== ================================= + \* matches everything + ? matches any single character + [seq] matches any character in seq + [!seq] matches any character not in seq + ========== ================================= + + .. versionchanged:: 1.4.0 + if the filter is a callable (function or method). It will be called + with the path and the file name as arguments for each file in dir. The + callable should returns True to indicate a match and False overwise. ''' filter_dirs = BooleanProperty(False) @@ -162,8 +173,8 @@ class FileChooserController(FloatLayout): sort_func = ObjectProperty(alphanumeric_folders_first) ''' :class:`~kivy.properties.ObjectProperty`. - Provides a function to be called with a list of filenames as the only argument. - Returns a list of filenames sorted for display in the view. + Provides a function to be called with a list of filenames as the only + argument. Returns a list of filenames sorted for display in the view. ''' files = ListProperty([]) @@ -202,9 +213,9 @@ class FileChooserController(FloatLayout): rootpath = StringProperty(None, allownone=True) ''' Root path to use, instead of the system root path. If set, it will not show - a ".." directory to go upper the root path. For example, if you set rootpath - to /Users/foo, the user will be unable to go to /Users, or to any other - directory not starting with /Users/foo. + a ".." directory to go upper the root path. For example, if you set + rootpath to /Users/foo, the user will be unable to go to /Users, or to any + other directory not starting with /Users/foo. .. versionadded:: 1.2.0 @@ -220,7 +231,6 @@ class FileChooserController(FloatLayout): :class:`FileChooserProgress` ''' - file_encodings = ListProperty(['utf-8', 'latin1', 'cp1252']) '''Possible encodings for decoding a filename to unicode. In the case that the user has a weird filename, undecodable without knowing it's @@ -358,7 +368,10 @@ class FileChooserController(FloatLayout): return files filtered = [] for filter in self.filters: - filtered.extend([fn for fn in files if fnmatch(fn, filter)]) + if callable(filter): + filtered.extend([fn for fn in files if filter(self.path, fn)]) + else: + filtered.extend([fn for fn in files if fnmatch(fn, filter)]) if not self.filter_dirs: dirs = [fn for fn in files if isdir(fn)] filtered.extend(dirs) @@ -403,8 +416,8 @@ class FileChooserController(FloatLayout): def _create_files_entries(self, *args): # create maximum entries during 50ms max, or 10 minimum (slow system) - # (on a "fast system" (core i7 2700K), we can create up to 40 entries in - # 50 ms. So 10 is fine for low system. + # (on a "fast system" (core i7 2700K), we can create up to 40 entries + # in 50 ms. So 10 is fine for low system. start = time() finished = False index = total = count = 1 @@ -445,16 +458,17 @@ class FileChooserController(FloatLayout): return False def cancel(self, *largs): - '''Cancel any background action started by filechooser, such as loading a - new directory. + '''Cancel any background action started by filechooser, such as loading + a new directory. .. versionadded:: 1.2.0 ''' Clock.unschedule(self._create_files_entries) self._hide_progress() if len(self._previous_path) > 1: - # if we cancel any action, the path will be set same as the previous - # one, so we can safely cancel the update of the previous path. + # if we cancel any action, the path will be set same as the + # previous one, so we can safely cancel the update of the previous + # path. self.path = self._previous_path[-2] Clock.unschedule(self._update_files) @@ -556,8 +570,8 @@ class FileChooserController(FloatLayout): yield index, total, entry def _force_unicode(self, s): - # the idea is, whatever is the filename, unicode or str, even if the str - # can't be directly returned as a unicode, return something. + # the idea is, whatever is the filename, unicode or str, even if the + # str can't be directly returned as a unicode, return something. if type(s) is unicode: return s encodings = self.file_encodings From e13ff57698fa37f03b49068b2a6754536512dcd6 Mon Sep 17 00:00:00 2001 From: tshirtman Date: Fri, 20 Jul 2012 16:37:00 +0300 Subject: [PATCH 26/86] fix broken link for python-for-android --- doc/sources/guide/packaging-android.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sources/guide/packaging-android.rst b/doc/sources/guide/packaging-android.rst index 270068bfc..29553390b 100644 --- a/doc/sources/guide/packaging-android.rst +++ b/doc/sources/guide/packaging-android.rst @@ -5,7 +5,7 @@ Create a package for Android .. versionchanged:: 1.1.0 Kivy-XXX-android.zip is not provided anymore. We are using - `python-for-android `_ + `python-for-android `_ (`doc `_) Packaging your application into APK From 9561b0088f46fd639a02368e180ac26ac384853e Mon Sep 17 00:00:00 2001 From: Qua-non Date: Sat, 21 Jul 2012 02:42:12 +0530 Subject: [PATCH 27/86] UIX:Markup allow valign, ensuring RstDoc isn't affected. Should fix #576 --- kivy/core/text/markup.py | 17 ++++++++++++++--- kivy/uix/rst.py | 19 +++++++++++++------ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/kivy/core/text/markup.py b/kivy/core/text/markup.py index cc9cacc33..1d05d14db 100644 --- a/kivy/core/text/markup.py +++ b/kivy/core/text/markup.py @@ -260,22 +260,33 @@ class MarkupLabel(MarkupLabelBase): r = self._render_text # convert halign/valign to int, faster comparaison - #av = {'top': 0, 'middle': 1, 'bottom': 2}[self.options['valign']] + av = {'top': 0, 'middle': 1, 'bottom': 2}[self.options['valign']] ah = {'left': 0, 'center': 1, 'right': 2}[self.options['halign']] y = 0 w, h = self._size refs = self._refs + no_of_lines = len(self._lines)-1 + for line in self._lines: lh = line[1] + lw = line[0] # horizontal alignement if ah == 0: x = 0 elif ah == 1: - x = int((w - line[0]) / 2) + x = int((w - lw) / 2) else: - x = w - line[0] + x = w - lw + + # vertical alignement + if y == 0: + if av == 1: + y = int((h - (lh*no_of_lines))/2) + elif av == 2: + y = h - (lh*(no_of_lines)) + for pw, ph, part, options in line[2]: self.options = options diff --git a/kivy/uix/rst.py b/kivy/uix/rst.py index 1763c4654..795f5af57 100644 --- a/kivy/uix/rst.py +++ b/kivy/uix/rst.py @@ -146,6 +146,7 @@ Builder.load_string(''' : markup: True + valign: 'top' font_size: 24 - self.section * 2 size_hint_y: None height: self.texture_size[1] + 20 @@ -162,6 +163,7 @@ Builder.load_string(''' : markup: True + valign: 'top' size_hint_y: None height: self.texture_size[1] + self.my text_size: self.width - self.mx, None @@ -174,6 +176,7 @@ Builder.load_string(''' id: label text: root.text markup: True + valign: 'top' size_hint: None, None size: self.texture_size[0] + 10, self.texture_size[1] + 10 @@ -210,6 +213,7 @@ Builder.load_string(''' Label: id: content markup: True + valign: 'top' text_size: self.width - 20, None font_name: 'data/fonts/DroidSansMono.ttf' color: (0, 0, 0, 1) @@ -296,6 +300,7 @@ Builder.load_string(''' : markup: True + valign: 'top' size_hint: None, 1 color: (0, 0, 0, 1) bold: True @@ -343,6 +348,7 @@ Builder.load_string(''' : markup: True + valign: 'top' size_hint_x: None width: self.texture_size[0] + 10 text_size: None, self.height - 10 @@ -431,8 +437,8 @@ class RstDocument(ScrollView): when a rst document is explicitly loaded, or where :func:`preload` has been called. - If the document has no filename, e.g., when the document is loaded from a text file, - the key will be ''. + If the document has no filename, e.g., when the document is loaded from a + text file, the key will be ''. :data:`toctrees` is a :class:`~kivy.properties.DictProperty`, default to {}. ''' @@ -541,10 +547,10 @@ class RstDocument(ScrollView): .. note:: - It is preferable to delay the call of the goto if you just loaded the - document, because the layout might not be finished, or if the size - of the RstDocument is not fixed yet, then the calculation of the - scrolling would be wrong. + It is preferable to delay the call of the goto if you just loaded + the document, because the layout might not be finished, or if the + size of the RstDocument is not fixed yet, then the calculation of + the scrolling would be wrong. However, you can do a direct call if the document is already loaded. @@ -687,6 +693,7 @@ class RstTransition(Widget): class RstEmptySpace(Widget): pass + class RstDefinitionSpace(Widget): pass From 265d9858db3ef14ece11e9d56395ea1640f22753 Mon Sep 17 00:00:00 2001 From: Qua-non Date: Sat, 21 Jul 2012 14:17:58 +0530 Subject: [PATCH 28/86] UIX:add_widget: raise Exception instead of just a warning on multiple parents --- kivy/uix/widget.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/kivy/uix/widget.py b/kivy/uix/widget.py index 5042c2100..a3c122ea0 100644 --- a/kivy/uix/widget.py +++ b/kivy/uix/widget.py @@ -65,7 +65,6 @@ from kivy.properties import NumericProperty, StringProperty, \ from kivy.graphics import Canvas from kivy.base import EventLoop from kivy.lang import Builder -from kivy.logger import Logger class WidgetException(Exception): @@ -231,10 +230,8 @@ class Widget(EventDispatcher): parent = widget.parent # check if widget is already a child of another widget if parent: - Logger.warning(''.join(('Cannot add Widget ', str(widget),\ - ' It already has a parent ', str(parent), - ' Skipping addition'))) - return + raise WidgetException(''.join(('Cannot add ', str(widget),\ + ' It already has a parent: ', str(parent)))) widget.parent = self if index == 0 or len(self.children) == 0: self.children.insert(0, widget) From 33ba4a3e228f1234771712c9b2a63fd257cf0910 Mon Sep 17 00:00:00 2001 From: Qua-non Date: Sat, 21 Jul 2012 16:00:15 +0530 Subject: [PATCH 29/86] UIX:Widget clean WidgetException remove ''.join --- kivy/uix/widget.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kivy/uix/widget.py b/kivy/uix/widget.py index a3c122ea0..151d201ae 100644 --- a/kivy/uix/widget.py +++ b/kivy/uix/widget.py @@ -230,8 +230,8 @@ class Widget(EventDispatcher): parent = widget.parent # check if widget is already a child of another widget if parent: - raise WidgetException(''.join(('Cannot add ', str(widget),\ - ' It already has a parent: ', str(parent)))) + raise WidgetException('Cannot add %r, it already has a parent %r' + % (widget, parent)) widget.parent = self if index == 0 or len(self.children) == 0: self.children.insert(0, widget) From 22d1f62aa64e7e93160d508016dc6212726ea3ee Mon Sep 17 00:00:00 2001 From: "gabriel.pettier" Date: Sat, 21 Jul 2012 16:26:41 +0200 Subject: [PATCH 30/86] add contribution guide --- doc/sources/guide/contribution.rst | 150 +++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 doc/sources/guide/contribution.rst diff --git a/doc/sources/guide/contribution.rst b/doc/sources/guide/contribution.rst new file mode 100644 index 000000000..7734166e4 --- /dev/null +++ b/doc/sources/guide/contribution.rst @@ -0,0 +1,150 @@ +Contribution +============ + +Coding rules +------------ + +- If you didn't do it yet, read the PEP8 about coding style in python + http://www.python.org/dev/peps/pep-0008/. +- Activate pep8 check on git commit like this:: + + make hook + +This will pass the code added to git staging zone (about to be committed) +thought a pep8 checker program when you do a commit, and check that you didn't +introduce pep8 errors, if so, the commit will be rejected, correct the errors, +and try again. + +Documentation +------------- + +Every module/class/method/function need a docstring, use the following keyword +when relevant + +- ``.. versionadded::`` to mark the version the feature was added. +- ``.. versionchanged::`` to mark the version behaviour of the feature was + changed. +- ``.. note::`` to add additional info about how to use the feature or related + feature. +- ``.. warning::`` to indicate a potential issue the user might run into using + the feature. + +Examples:: + + def my_new_feature(self, arg): + """ + New feature is awesome + + .. versionadded:: 1.1.4 + + .. note:: This new feature will likely blow your mind + + .. warning:: Please take a seat before trying this feature + """ + +Will result in: + + def my_new_feature(self, arg): + """ + New feature is awesome + + .. versionadded:: 1.1.4 + + .. note:: This new feature will likely blow your mind + + .. warning:: Please take a seat before trying this feature + """ + + +When refering to other parts of the api use: + +- ``:mod:`~kivy.module``` to refer to a module +- ``:class:`~kivy.module.Class``` to refer to a class +- ``:meth:`~kivy.module.Class.method``` to refer to a method +- ``:doc:`api-kivy.module``` to refer to the documentation of a module (same + for a class and a method) + +Obviously replacing `module` `class` and `method` with their real name, and +using using '.' to separate modules refering to imbricated modules, e.g:: + + :mod:`~kivy.uix.floatlayout` + :class:`~kivy.uix.floatlayout.FloatLayout` + :meth:`~kivy.core.window.WindowBase.toggle_fullscreen` + :doc:`/api-kivy.core.window` + +Will result in + + :mod:`~kivy.uix.floatlayout` + :class:`~kivy.uix.floatlayout.FloatLayout` + :meth:`~kivy.core.window.WindowBase.toggle_fullscreen` + :doc:`/api-kivy.core.window` + +`:doc:` and `:mod:` are essentially the same, except for an anchor in the url, +this makes `:doc:` prefered, for the cleaner url: + +Tests +----- + +Tests in kivy are easy to write, they are based on the unittest module and easy +to start, think about them, tests makes a project stronger ! + +Look into `kivy/tests` and, if you encounter a bug in kivy, or add a feature to +kivy, please try to write a simple tests that tries the concerned feature, +showing a potential bug. + + +Performances +------------ + +- take care of performance issues, read + http://wiki.python.org/moin/PythonSpeed/PerformanceTips +- cpu intensive parts of Kivy are written in cython, if you are doing a lot of + computation, consider using it too. + +Workflow +-------- + +- For new features or big corrections, consider creating a branch on your fork, + and do the pull request from the branch. + +Example using git command line, assuming you forked kivy on github and cloned +locally using the url provided by github: + +Creating a branch:: + + git chekcout -b my_new_feature + +Do some changes, add them to the future commit:: + + git add -p + +If you created files that need to be tracked:: + + git add filenames + +Then commit:: + + git commit + +If your commit fixes a bug referenced in the tracker, putting:: + + closes: #XXX + +in the commit message is a good thing, XXX being the issue number. + +Please think about committing regularly, committing when things works better +than the last commits, is a good rule + +Push your changes to your github repos:: + + git push + +Then, from the Github repos, click on the `pull request` button at the top of +the page, make sure you are requesting your merge to be done from your feature +branch to kivy master branch, and add a short text describing why you think +your changes should be merged. + +You can do a pull request even if you are not totally sure you followed all the +recomendations to the letter, we will review and suggest changes if we feel +some more work is required, the pull request will be automatically updated when +you'll push new changes, so no worry doing the pull request early. From ab8ffc3d31b93cb09e710b221496b2db95a9ad66 Mon Sep 17 00:00:00 2001 From: "gabriel.pettier" Date: Sat, 21 Jul 2012 16:29:45 +0200 Subject: [PATCH 31/86] add contribution in the guide. --- doc/sources/guide-index.rst | 2 +- doc/sources/guide/contribution.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/sources/guide-index.rst b/doc/sources/guide-index.rst index d0a71482b..5456ec13a 100644 --- a/doc/sources/guide-index.rst +++ b/doc/sources/guide-index.rst @@ -17,4 +17,4 @@ Programming Guide guide/designwithkv guide/other-frameworks guide/packaging - + guide/contribution diff --git a/doc/sources/guide/contribution.rst b/doc/sources/guide/contribution.rst index 7734166e4..1e82ff2aa 100644 --- a/doc/sources/guide/contribution.rst +++ b/doc/sources/guide/contribution.rst @@ -80,7 +80,7 @@ Will result in :doc:`/api-kivy.core.window` `:doc:` and `:mod:` are essentially the same, except for an anchor in the url, -this makes `:doc:` prefered, for the cleaner url: +this makes `:doc:` prefered, for the cleaner url. Tests ----- From 40ef39ecdb116b148af448fdbd37bebcb0c29afb Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Thu, 12 Jul 2012 06:56:33 +0200 Subject: [PATCH 32/86] add ModalView --- kivy/data/images/defaulttheme.atlas | 2 +- kivy/data/style.kv | 10 +- kivy/uix/modalview.py | 263 ++++++++++++++++++++++++++++ kivy/uix/popup.py | 173 ++---------------- 4 files changed, 282 insertions(+), 166 deletions(-) create mode 100644 kivy/uix/modalview.py diff --git a/kivy/data/images/defaulttheme.atlas b/kivy/data/images/defaulttheme.atlas index 73ab951c4..21a3377c6 100644 --- a/kivy/data/images/defaulttheme.atlas +++ b/kivy/data/images/defaulttheme.atlas @@ -1 +1 @@ -{"defaulttheme-0.png": {"player-play-overlay": [306, 396, 117, 115], "progressbar_background": [160, 137, 24, 24], "media-playback-pause": [448, 344, 48, 48], "tab_btn_pressed": [465, 178, 32, 32], "image-missing": [399, 344, 48, 48], "filechooser_selected": [187, 393, 118, 118], "audio-volume-muted": [350, 344, 48, 48], "sliderv_background": [473, 404, 37, 41], "tab": [332, 228, 96, 32], "close": [490, 491, 20, 20], "ring": [1, 326, 185, 185], "vkeyboard_key_down": [61, 129, 32, 32], "vkeyboard_background": [187, 328, 64, 64], "checkbox_off": [300, 178, 32, 32], "bubble_arrow": [148, 162, 16, 10], "player-background": [228, 222, 103, 103], "bubble": [424, 446, 65, 65], "sliderh_background": [148, 173, 41, 37], "audio-volume-medium": [301, 344, 48, 48], "media-playback-start": [1, 162, 48, 48], "tab_btn": [432, 178, 32, 32], "bubble_btn_pressed": [267, 178, 32, 32], "tree_closed": [490, 470, 20, 20], "switch-background": [429, 228, 83, 32], "filechooser_file": [332, 261, 64, 64], "checkbox_radio_off": [366, 178, 32, 32], "vkeyboard_key_normal": [94, 129, 32, 32], "checkbox_radio_on": [399, 178, 32, 32], "checkbox_on": [333, 178, 32, 32], "tree_opened": [490, 449, 20, 20], "button_pressed": [31, 124, 29, 37], "media-playback-stop": [50, 162, 48, 48], "audio-volume-high": [424, 397, 48, 48], "audio-volume-low": [252, 344, 48, 48], "bubble_btn": [234, 178, 32, 32], "slider_cursor": [99, 162, 48, 48], "button": [1, 124, 29, 37], "progressbar": [127, 137, 32, 24], "switch-button": [190, 178, 43, 32], "filechooser_folder": [397, 261, 64, 64], "popup-background": [462, 271, 45, 54], "textinput_active": [1, 211, 114, 114], "textinput": [116, 214, 111, 111]}} \ No newline at end of file +{"defaulttheme-0.png": {"player-play-overlay": [306, 396, 117, 115], "progressbar_background": [160, 137, 24, 24], "media-playback-pause": [448, 344, 48, 48], "tab_btn_pressed": [465, 178, 32, 32], "image-missing": [399, 344, 48, 48], "filechooser_selected": [187, 393, 118, 118], "audio-volume-muted": [350, 344, 48, 48], "sliderv_background": [473, 404, 37, 41], "tab": [332, 228, 96, 32], "close": [490, 491, 20, 20], "ring": [1, 326, 185, 185], "vkeyboard_key_down": [61, 129, 32, 32], "vkeyboard_background": [187, 328, 64, 64], "checkbox_off": [300, 178, 32, 32], "bubble_arrow": [148, 162, 16, 10], "player-background": [228, 222, 103, 103], "bubble": [424, 446, 65, 65], "sliderh_background": [148, 173, 41, 37], "audio-volume-medium": [301, 344, 48, 48], "media-playback-start": [1, 162, 48, 48], "tab_btn": [432, 178, 32, 32], "bubble_btn_pressed": [267, 178, 32, 32], "tree_closed": [490, 470, 20, 20], "switch-background": [429, 228, 83, 32], "filechooser_file": [332, 261, 64, 64], "checkbox_radio_off": [366, 178, 32, 32], "vkeyboard_key_normal": [94, 129, 32, 32], "checkbox_radio_on": [399, 178, 32, 32], "checkbox_on": [333, 178, 32, 32], "tree_opened": [490, 449, 20, 20], "button_pressed": [31, 124, 29, 37], "media-playback-stop": [50, 162, 48, 48], "audio-volume-high": [424, 397, 48, 48], "audio-volume-low": [252, 344, 48, 48], "bubble_btn": [234, 178, 32, 32], "slider_cursor": [99, 162, 48, 48], "button": [1, 124, 29, 37], "progressbar": [127, 137, 32, 24], "switch-button": [190, 178, 43, 32], "filechooser_folder": [397, 261, 64, 64], "popup-background": [462, 271, 45, 54], "modalview-background": [462, 271, 45, 54], "textinput_active": [1, 211, 114, 114], "textinput": [116, 214, 111, 111]}} \ No newline at end of file diff --git a/kivy/data/style.kv b/kivy/data/style.kv index b489e7a5e..880f42841 100644 --- a/kivy/data/style.kv +++ b/kivy/data/style.kv @@ -388,9 +388,9 @@ size: 43, 32 pos: int(self.center_x - 41 + self.active_norm_pos * 41), int(self.center_y - 16) -# Popup widget -: - _container: container + +# ModalView widget +: canvas: Color: rgba: root.background_color[:3] + [root.background_color[-1] * self._anim_alpha] @@ -405,6 +405,10 @@ pos: self.pos size: self.size + +# Popup widget +: + _container: container GridLayout: padding: 12 cols: 1 diff --git a/kivy/uix/modalview.py b/kivy/uix/modalview.py new file mode 100644 index 000000000..102114b49 --- /dev/null +++ b/kivy/uix/modalview.py @@ -0,0 +1,263 @@ +''' +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, deactivate the size_hint and use a specific +size attribute. + +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() + +''' + +__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(.100) + + _window = ObjectProperty(None, allownone=True) + + def __init__(self, **kwargs): + self.register_event_type('on_open') + self.register_event_type('on_dismiss') + 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`. + ''' + # 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) + self.center = self._window.center + Animation(_anim_alpha=1., d=self._anim_duration).start(self) + self.dispatch('on_open') + return self + + 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 + 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._window.remove_widget(self) + self._window.unbind(on_resize=self._align_center) + self._window = None + + def on_open(self): + pass + + def on_dismiss(self): + pass + + +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() diff --git a/kivy/uix/popup.py b/kivy/uix/popup.py index bd2c1ff0d..8c806e57d 100644 --- a/kivy/uix/popup.py +++ b/kivy/uix/popup.py @@ -69,7 +69,7 @@ __all__ = ('Popup', 'PopupException') from kivy.logger import Logger from kivy.animation import Animation -from kivy.uix.floatlayout import FloatLayout +from kivy.uix.modalview import ModalView from kivy.properties import StringProperty, BooleanProperty, ObjectProperty, \ NumericProperty, ListProperty @@ -81,7 +81,7 @@ class PopupException(Exception): ''' -class Popup(FloatLayout): +class Popup(ModalView): '''Popup class. See module documentation for more information. :Events: @@ -99,23 +99,6 @@ class Popup(FloatLayout): title'. ''' - auto_dismiss = BooleanProperty(True) - '''Default to True, this property determines if the popup 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 popup 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. - ''' - content = ObjectProperty(None) '''Content of the popup that is displayed just under the title. @@ -123,39 +106,6 @@ class Popup(FloatLayout): None. ''' - background_color = ListProperty([0, 0, 0, .7]) - '''Background color, in the format (r, g, b, a). - - .. versionadded:: 1.1.0 - - :data:`background_color` is a :class:`~kivy.properties.ListProperty`, - default to [0, 0, 0, .7]. - ''' - - background = StringProperty( - 'atlas://data/images/defaulttheme/popup-background') - '''Background image of the popup used for the popup background. - - .. versionadded:: 1.1.0 - - :data:`background` is an :class:`~kivy.properties.StringProperty`, - default to 'atlas://data/images/defaulttheme/popup-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. - - .. versionadded:: 1.1.0 - - 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) - ''' - separator_color = ListProperty([47 / 255., 167 / 255., 212 / 255., 1.]) '''Color used by the separator between title and content. @@ -178,30 +128,10 @@ class Popup(FloatLayout): _container = ObjectProperty(None) - _anim_alpha = NumericProperty(0) - - _anim_duration = NumericProperty(.100) - - _window = ObjectProperty(None, allownone=True) - def __init__(self, **kwargs): - self.register_event_type('on_open') - self.register_event_type('on_dismiss') - self._parent = None + kwargs.setdefault('background', 'atlas://data/images/defaulttheme/popup-background') super(Popup, 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 add_widget(self, widget): if self._container: if self.content: @@ -210,82 +140,6 @@ class Popup(FloatLayout): else: super(Popup, self).add_widget(widget) - def open(self, *largs): - '''Show the popup 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 popup will attach to the global - :class:`~kivy.core.window.Window`. - ''' - # search window - self._window = self._search_window() - if not self._window: - Logger.warning('Popup: cannot open popup, no window found.') - return self - self._window.add_widget(self) - self._window.bind(on_resize=self._align_center) - self.center = self._window.center - Animation(_anim_alpha=1., d=self._anim_duration).start(self) - self.dispatch('on_open') - return self - - def dismiss(self, *largs, **kwargs): - '''Close the popup if it is open. If you really want to close the - popup, whatever the on_dismiss event returns, you can do this: - :: - - popup = Popup(...) - popup.dismiss(force=True) - - .. versionchanged:: 1.3.0 - When the popup is dismissed, it will be faded out, before - removal from the parent. If you don't want animation, use: - `popup.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 - 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(Popup, self).on_touch_down(touch) - return True - - def on_touch_move(self, touch): - super(Popup, self).on_touch_move(touch) - return True - - def on_touch_up(self, touch): - super(Popup, self).on_touch_up(touch) - return True - - def on__anim_alpha(self, instance, value): - if value == 0 and self._window is not None: - self._window.remove_widget(self) - self._window.unbind(on_resize=self._align_center) - self._window = None - def on_content(self, instance, value): if not hasattr(value, 'popup'): value.create_property('popup') @@ -300,12 +154,6 @@ class Popup(FloatLayout): self._container.clear_widgets() self._container.add_widget(self.content) - def on_open(self): - pass - - def on_dismiss(self): - pass - if __name__ == '__main__': from kivy.base import runTouchApp @@ -314,12 +162,6 @@ if __name__ == '__main__': from kivy.uix.gridlayout import GridLayout from kivy.core.window import Window - layout = GridLayout(cols=3) - for x in xrange(9): - btn = Button(text=str(x)) - layout.add_widget(btn) - Window.add_widget(layout) - # add popup content = GridLayout(cols=1) content_cancel = Button(text='Cancel', size_hint_y=None, height=40) @@ -329,7 +171,14 @@ if __name__ == '__main__': size_hint=(None, None), size=(256, 256), content=content) content_cancel.bind(on_release=popup.dismiss) - btn.bind(on_release=popup.open) + + layout = GridLayout(cols=3) + for x in xrange(9): + btn = Button(text=str(x)) + btn.bind(on_release=popup.open) + layout.add_widget(btn) + + Window.add_widget(layout) popup.open() From 68d18b5f84fcbde88ec7c6c7f2e08acc7bd96ba8 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Fri, 13 Jul 2012 10:49:14 +0200 Subject: [PATCH 33/86] add modalview to factory --- kivy/factory_registers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/kivy/factory_registers.py b/kivy/factory_registers.py index df21bd547..93d274cce 100644 --- a/kivy/factory_registers.py +++ b/kivy/factory_registers.py @@ -89,6 +89,7 @@ r('Image', module='kivy.uix.image') r('AsyncImage', module='kivy.uix.image') r('Label', module='kivy.uix.label') r('Layout', module='kivy.uix.layout') +r('ModalView', module='kivy.uix.modalview') r('ProgressBar', module='kivy.uix.progressbar') r('Popup', module='kivy.uix.popup') r('Scatter', module='kivy.uix.scatter') From d6b8915a1d1d9a82875a638c960a09523a087760 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Sat, 21 Jul 2012 22:45:31 +0200 Subject: [PATCH 34/86] fix doc and __all__ --- kivy/uix/modalview.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kivy/uix/modalview.py b/kivy/uix/modalview.py index 102114b49..7b49af9e7 100644 --- a/kivy/uix/modalview.py +++ b/kivy/uix/modalview.py @@ -1,6 +1,6 @@ ''' ModalView -===== +========= .. versionadded:: 1.4.0 @@ -46,7 +46,7 @@ can directly bind the function to an action, e.g., to a button's on_press :: 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 @@ -62,7 +62,7 @@ view from closing by explictly returning True from your callback :: ''' -__all__ = ('ModalView') +__all__ = ('ModalView',) from kivy.logger import Logger from kivy.animation import Animation From 25be28646bb09a56d4baf8c747f542adb7980dda Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Sat, 21 Jul 2012 22:45:51 +0200 Subject: [PATCH 35/86] fix doc and remove __init__ --- kivy/uix/popup.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/kivy/uix/popup.py b/kivy/uix/popup.py index 8c806e57d..18b8f4695 100644 --- a/kivy/uix/popup.py +++ b/kivy/uix/popup.py @@ -15,6 +15,11 @@ Remember that the default size of a Widget is size_hint=(1, 1). If you don't want your popup to be fullscreen, deactivate the size_hint and use a specific size attribute. + +.. versionchanged:: 1.4.0 + The :class:`Popup` class now inherits from :class:`~kivy.uix.modalview.ModalView`. + The :class:`Popup` offers a default layout with a title and a separation bar. + Examples -------- @@ -99,6 +104,14 @@ class Popup(ModalView): title'. ''' + background = StringProperty( + 'atlas://data/images/defaulttheme/popup-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/popup-background' + ''' + content = ObjectProperty(None) '''Content of the popup that is displayed just under the title. @@ -128,10 +141,6 @@ class Popup(ModalView): _container = ObjectProperty(None) - def __init__(self, **kwargs): - kwargs.setdefault('background', 'atlas://data/images/defaulttheme/popup-background') - super(Popup, self).__init__(**kwargs) - def add_widget(self, widget): if self._container: if self.content: From e4068d3ebaabfe868520e3e9fbae407b437dd545 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Sat, 21 Jul 2012 22:56:02 +0200 Subject: [PATCH 36/86] remove useless imports --- kivy/uix/popup.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/kivy/uix/popup.py b/kivy/uix/popup.py index 18b8f4695..5cbad720c 100644 --- a/kivy/uix/popup.py +++ b/kivy/uix/popup.py @@ -72,10 +72,8 @@ popup from closing by explictly returning True from your callback :: __all__ = ('Popup', 'PopupException') -from kivy.logger import Logger -from kivy.animation import Animation from kivy.uix.modalview import ModalView -from kivy.properties import StringProperty, BooleanProperty, ObjectProperty, \ +from kivy.properties import StringProperty, ObjectProperty, \ NumericProperty, ListProperty From 96a86ea05e5310db6dbcfe7f6e4ce3f0c411d704 Mon Sep 17 00:00:00 2001 From: "gabriel.pettier" Date: Sun, 22 Jul 2012 01:15:45 +0200 Subject: [PATCH 37/86] merge doc/guide/contribution.rst with doc/contribute.rst --- doc/sources/contribute.rst | 114 +++++++++++++++++++++- doc/sources/guide-index.rst | 1 - doc/sources/guide/contribution.rst | 150 ----------------------------- 3 files changed, 109 insertions(+), 156 deletions(-) delete mode 100644 doc/sources/guide/contribution.rst diff --git a/doc/sources/contribute.rst b/doc/sources/contribute.rst index b0f5709cf..fb75f3ba0 100644 --- a/doc/sources/contribute.rst +++ b/doc/sources/contribute.rst @@ -58,6 +58,30 @@ your contribution won't be forgotten or lost. Also, your name will always be associated with the change you made, which basically means eternal fame in our code history (you can opt-out if you don't want that). + +Coding style +~~~~~~~~~~~~ + +- If you didn't do it yet, read the `PEP8 < + http://www.python.org/dev/peps/pep-0008/>` about coding style in python. + +- Activate pep8 check on git commit like this:: + + make hook + +This will pass the code added to git staging zone (about to be committed) +thought a pep8 checker program when you do a commit, and check that you didn't +introduce pep8 errors, if so, the commit will be rejected, correct the errors, +and try again. + +Performances +~~~~~~~~~~~~ + +- take care of performance issues, read `Python performance tips < + http://wiki.python.org/moin/PythonSpeed/PerformanceTips>` +- cpu intensive parts of Kivy are written in cython, if you are doing a lot of + computation, consider using it too. + Git & GitHub ~~~~~~~~~~~~ @@ -91,9 +115,12 @@ but the fork you create with the following steps: #. Compile and set up PYTHONPATH or install (see :ref:`dev-install`). #. Install our pre-commit hook that ensures your code doesn't violate our styleguide by executing `make hook` from the root directory of your - clone. This will run our styleguide check whenever you do a commit, - and if there are violations in the parts that you changed, your commit + clone. This will run our styleguide check whenever you do a commit, + and if there are violations in the parts that you changed, your commit will be aborted. Fix & retry. + #. Add kivy repo as a remote source:: + + git remote add kivy https://github.com/kivy/kivy.git Now, whenever you want to create a patch, you follow the following steps: @@ -102,7 +129,10 @@ Now, whenever you want to create a patch, you follow the following steps: #. Create a new, appropriately named branch in your local repository for that specific feature or bugfix. (Keeping a new branch per feature makes sure we can easily pull in your - changes without pulling any other stuff that is not supposed to be pulled.) + changes without pulling any other stuff that is not supposed to be pulled.):: + + git checkout -b new_feature + #. Modify the code to do what you want (e.g., fix it). #. Test the code. Try to do this even for small fixes. You never know whether you have introduced some weird bug without testing. @@ -114,8 +144,14 @@ Now, whenever you want to create a patch, you follow the following steps: not familiar with the matter get a good idea of what you changed. #. Once you are satisfied with your changes, merge with our upstream repository. We can pull your stuff, but since you know best what you - changed, you should do the merge. - #. Push to your remote repository on GitHub. + changed, you should do the merge:: + + git pull kivy master + + #. Push to your remote repository on GitHub:: + + git push + #. Send a *Pull Request* with a description of what you changed via the button in the GitHub interface of your repository. (This is why we forked initially. Your repository is linked against ours.) @@ -145,6 +181,74 @@ hassle just to correct a single typo. For more complex contributions, please consider following the suggested workflow though. +Docstrings +~~~~~~~~~~ + +Every module/class/method/function need a docstring, use the following keyword +when relevant + +- ``.. versionadded::`` to mark the version the feature was added. +- ``.. versionchanged::`` to mark the version behaviour of the feature was + changed. +- ``.. note::`` to add additional info about how to use the feature or related + feature. +- ``.. warning::`` to indicate a potential issue the user might run into using + the feature. + +Examples:: + + def my_new_feature(self, arg): + """ + New feature is awesome + + .. versionadded:: 1.1.4 + + .. note:: This new feature will likely blow your mind + + .. warning:: Please take a seat before trying this feature + """ + +Will result in: + + def my_new_feature(self, arg): + """ + New feature is awesome + + .. versionadded:: 1.1.4 + + .. note:: This new feature will likely blow your mind + + .. warning:: Please take a seat before trying this feature + """ + + +When refering to other parts of the api use: + +- ``:mod:`~kivy.module``` to refer to a module +- ``:class:`~kivy.module.Class``` to refer to a class +- ``:meth:`~kivy.module.Class.method``` to refer to a method +- ``:doc:`api-kivy.module``` to refer to the documentation of a module (same + for a class and a method) + +Obviously replacing `module` `class` and `method` with their real name, and +using using '.' to separate modules refering to imbricated modules, e.g:: + + :mod:`~kivy.uix.floatlayout` + :class:`~kivy.uix.floatlayout.FloatLayout` + :meth:`~kivy.core.window.WindowBase.toggle_fullscreen` + :doc:`/api-kivy.core.window` + +Will result in: + + :mod:`~kivy.uix.floatlayout` + :class:`~kivy.uix.floatlayout.FloatLayout` + :meth:`~kivy.core.window.WindowBase.toggle_fullscreen` + :doc:`/api-kivy.core.window` + +`:doc:` and `:mod:` are essentially the same, except for an anchor in the url, +this makes `:doc:` prefered, for the cleaner url. + + Unit tests contributions ------------------------ diff --git a/doc/sources/guide-index.rst b/doc/sources/guide-index.rst index 5456ec13a..d503d7d66 100644 --- a/doc/sources/guide-index.rst +++ b/doc/sources/guide-index.rst @@ -17,4 +17,3 @@ Programming Guide guide/designwithkv guide/other-frameworks guide/packaging - guide/contribution diff --git a/doc/sources/guide/contribution.rst b/doc/sources/guide/contribution.rst deleted file mode 100644 index 1e82ff2aa..000000000 --- a/doc/sources/guide/contribution.rst +++ /dev/null @@ -1,150 +0,0 @@ -Contribution -============ - -Coding rules ------------- - -- If you didn't do it yet, read the PEP8 about coding style in python - http://www.python.org/dev/peps/pep-0008/. -- Activate pep8 check on git commit like this:: - - make hook - -This will pass the code added to git staging zone (about to be committed) -thought a pep8 checker program when you do a commit, and check that you didn't -introduce pep8 errors, if so, the commit will be rejected, correct the errors, -and try again. - -Documentation -------------- - -Every module/class/method/function need a docstring, use the following keyword -when relevant - -- ``.. versionadded::`` to mark the version the feature was added. -- ``.. versionchanged::`` to mark the version behaviour of the feature was - changed. -- ``.. note::`` to add additional info about how to use the feature or related - feature. -- ``.. warning::`` to indicate a potential issue the user might run into using - the feature. - -Examples:: - - def my_new_feature(self, arg): - """ - New feature is awesome - - .. versionadded:: 1.1.4 - - .. note:: This new feature will likely blow your mind - - .. warning:: Please take a seat before trying this feature - """ - -Will result in: - - def my_new_feature(self, arg): - """ - New feature is awesome - - .. versionadded:: 1.1.4 - - .. note:: This new feature will likely blow your mind - - .. warning:: Please take a seat before trying this feature - """ - - -When refering to other parts of the api use: - -- ``:mod:`~kivy.module``` to refer to a module -- ``:class:`~kivy.module.Class``` to refer to a class -- ``:meth:`~kivy.module.Class.method``` to refer to a method -- ``:doc:`api-kivy.module``` to refer to the documentation of a module (same - for a class and a method) - -Obviously replacing `module` `class` and `method` with their real name, and -using using '.' to separate modules refering to imbricated modules, e.g:: - - :mod:`~kivy.uix.floatlayout` - :class:`~kivy.uix.floatlayout.FloatLayout` - :meth:`~kivy.core.window.WindowBase.toggle_fullscreen` - :doc:`/api-kivy.core.window` - -Will result in - - :mod:`~kivy.uix.floatlayout` - :class:`~kivy.uix.floatlayout.FloatLayout` - :meth:`~kivy.core.window.WindowBase.toggle_fullscreen` - :doc:`/api-kivy.core.window` - -`:doc:` and `:mod:` are essentially the same, except for an anchor in the url, -this makes `:doc:` prefered, for the cleaner url. - -Tests ------ - -Tests in kivy are easy to write, they are based on the unittest module and easy -to start, think about them, tests makes a project stronger ! - -Look into `kivy/tests` and, if you encounter a bug in kivy, or add a feature to -kivy, please try to write a simple tests that tries the concerned feature, -showing a potential bug. - - -Performances ------------- - -- take care of performance issues, read - http://wiki.python.org/moin/PythonSpeed/PerformanceTips -- cpu intensive parts of Kivy are written in cython, if you are doing a lot of - computation, consider using it too. - -Workflow --------- - -- For new features or big corrections, consider creating a branch on your fork, - and do the pull request from the branch. - -Example using git command line, assuming you forked kivy on github and cloned -locally using the url provided by github: - -Creating a branch:: - - git chekcout -b my_new_feature - -Do some changes, add them to the future commit:: - - git add -p - -If you created files that need to be tracked:: - - git add filenames - -Then commit:: - - git commit - -If your commit fixes a bug referenced in the tracker, putting:: - - closes: #XXX - -in the commit message is a good thing, XXX being the issue number. - -Please think about committing regularly, committing when things works better -than the last commits, is a good rule - -Push your changes to your github repos:: - - git push - -Then, from the Github repos, click on the `pull request` button at the top of -the page, make sure you are requesting your merge to be done from your feature -branch to kivy master branch, and add a short text describing why you think -your changes should be merged. - -You can do a pull request even if you are not totally sure you followed all the -recomendations to the letter, we will review and suggest changes if we feel -some more work is required, the pull request will be automatically updated when -you'll push new changes, so no worry doing the pull request early. From a3b082e4d1fd4ede96810505e53e8b1853789951 Mon Sep 17 00:00:00 2001 From: "gabriel.pettier" Date: Sun, 22 Jul 2012 01:19:55 +0200 Subject: [PATCH 38/86] fix links to PEP8 and python performance tips --- doc/sources/contribute.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/sources/contribute.rst b/doc/sources/contribute.rst index fb75f3ba0..42f1c325b 100644 --- a/doc/sources/contribute.rst +++ b/doc/sources/contribute.rst @@ -62,8 +62,8 @@ code history (you can opt-out if you don't want that). Coding style ~~~~~~~~~~~~ -- If you didn't do it yet, read the `PEP8 < - http://www.python.org/dev/peps/pep-0008/>` about coding style in python. +- If you didn't do it yet, read the + `PEP8 `_ about coding style in python. - Activate pep8 check on git commit like this:: @@ -77,8 +77,8 @@ and try again. Performances ~~~~~~~~~~~~ -- take care of performance issues, read `Python performance tips < - http://wiki.python.org/moin/PythonSpeed/PerformanceTips>` +- take care of performance issues, read + `Python performance tips `_ - cpu intensive parts of Kivy are written in cython, if you are doing a lot of computation, consider using it too. From 95e9d5a48a1e89b4ee6b1abdb5f7db94a482cad6 Mon Sep 17 00:00:00 2001 From: Qua-non Date: Tue, 24 Jul 2012 02:25:41 +0530 Subject: [PATCH 39/86] Vkeyboard: Request Android keyboard only if vkeyboard isn't enabled. --- kivy/core/window/window_pygame.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kivy/core/window/window_pygame.py b/kivy/core/window/window_pygame.py index 53668bc2b..b18f688ec 100644 --- a/kivy/core/window/window_pygame.py +++ b/kivy/core/window/window_pygame.py @@ -345,7 +345,7 @@ class WindowPygame(WindowBase): def request_keyboard(self, *largs): keyboard = super(WindowPygame, self).request_keyboard(*largs) - if android: + if android and not self.allow_vkeyboard: android.show_keyboard() return keyboard From c0cdbe74ce903c0880dda18220a88a9542bc897a Mon Sep 17 00:00:00 2001 From: Qua-non Date: Tue, 24 Jul 2012 04:38:53 +0530 Subject: [PATCH 40/86] Doc: GettingStarted: replace absolute paths with relative --- doc/sources/gettingstarted/diving.rst | 16 ++++++++-------- doc/sources/gettingstarted/drawing.rst | 2 +- doc/sources/gettingstarted/examples.rst | 8 ++++---- doc/sources/gettingstarted/framework.rst | 8 ++++---- doc/sources/gettingstarted/layouts.rst | 12 +++++++----- doc/sources/gettingstarted/properties.rst | 20 ++++++++++---------- 6 files changed, 34 insertions(+), 32 deletions(-) diff --git a/doc/sources/gettingstarted/diving.rst b/doc/sources/gettingstarted/diving.rst index 31fe801ab..6f8e933d4 100644 --- a/doc/sources/gettingstarted/diving.rst +++ b/doc/sources/gettingstarted/diving.rst @@ -6,23 +6,23 @@ Diving in To further get into kivy take a look at :doc:`/index` -Kivy comes with a set of :doc:`examples` in the ``examples`` directory. +Kivy comes with a set of :doc:`examples` in the ``kivy_installation/examples`` directory. You should try modifying/improving/adapting them to your needs. Browse the `snippet wiki `_ . You can even add your snippet in the user snippets section. -Understand the basics about `kivy graphics `_ +Understand the basics about :mod:`kivy graphics ` -Take a look at the built-in `widgets `_ +Take a look at the built-in :mod:`widgets ` -Follow the `programming guide `_ to get even more familiar with kivy. +Follow the :doc:`/guide-index` to get even more familiar with kivy. -See how to use different `Modules `_ like the Inspector for live inspection in the modules section. +See how to use different :mod:`Modules ` like the Inspector for live inspection in the modules section. -Learn how to handle custom `Input `_ +Learn how to handle custom :mod:`Input ` -See how kivy has been extended with `extensions `_ support. +See how kivy has been extended with :mod:`extensions ` support. -Familiarize yourself with the `kivy framework `_ +Familiarize yourself with the :mod:`kivy framework ` Kivy is open source so you can **contribute** , take a look at :doc:`/contribute` section to see the guidelines. diff --git a/doc/sources/gettingstarted/drawing.rst b/doc/sources/gettingstarted/drawing.rst index f19ff38e4..9e5e7ead0 100644 --- a/doc/sources/gettingstarted/drawing.rst +++ b/doc/sources/gettingstarted/drawing.rst @@ -17,4 +17,4 @@ In both cases the canvas of the MyWidget is re-drawn whenever the ``position`` o You can use **canvas.before** or **canvas.after** . This allows you to separate your instructions based on when you want them to happen. -For an in-depth look at how Kivy's graphics are handled, look `here. `_ +For an in-depth look at how Kivy's graphics are handled, look :mod:`here. ` diff --git a/doc/sources/gettingstarted/examples.rst b/doc/sources/gettingstarted/examples.rst index 1500a0550..51796b08b 100644 --- a/doc/sources/gettingstarted/examples.rst +++ b/doc/sources/gettingstarted/examples.rst @@ -58,7 +58,7 @@ Examples .. |tws_dir| replace:: ./examples/frameworks/twisted .. |tws_file| replace:: echo_client_app.py .. |tws_file2| replace:: echo_server_app.py -.. |tws_desc| replace:: A clent and server app using `twisted-inside-kivy `__ +.. |tws_desc| replace:: A clent and server app using :doc:`Twisted inside Kivy ` .. |gst_dir| replace:: ./examples/gestures .. |gst_file| replace:: gesture_board.py @@ -66,7 +66,7 @@ Examples .. |kv_dir| replace:: ./examples/guide/designwithkv .. |kv_file| replace:: main.py -.. |kv_desc| replace:: Programming Guide examples on how to `design with kv lang `__. +.. |kv_desc| replace:: Programming Guide examples on how to :doc:`design with kv lang ` .. |fwd_dir| replace:: ./examples/guide/firstwidget .. |fwd_file| replace:: 1_skeleton.py @@ -75,11 +75,11 @@ Examples .. |fwd_file4| replace:: 4_draw_line.py .. |fwd_file5| replace:: 5_random_colors.py .. |fwd_file6| replace:: 6_button.py -.. |fwd_desc| replace:: Programming Guide examples `Your first widget `__ . +.. |fwd_desc| replace:: Programming Guide examples :doc:`Your first widget ` .. |qst_dir| replace:: ./examples/guide/quickstart .. |qst_file| replace:: main.py -.. |qst_desc| replace:: Programming Guide `guide/quickstart `__ example. +.. |qst_desc| replace:: Programming Guide :doc:`guide/quickstart ` example. .. |kin_dir| replace:: ./examples/kinect .. |kin_file| replace:: main.py diff --git a/doc/sources/gettingstarted/framework.rst b/doc/sources/gettingstarted/framework.rst index 7a1964b9b..a42310cf9 100644 --- a/doc/sources/gettingstarted/framework.rst +++ b/doc/sources/gettingstarted/framework.rst @@ -17,10 +17,10 @@ Non-widget stuff .. |clock_text| replace:: :class:`Clock ` provides you with a convenient way to do jobs at set time intervals and is preferred over *sleep()* which would block the kivy Event Loop. These intervals can be set relative to the OpenGL Drawing instructions, :ref:`before ` or :ref:`after ` frame. Clock also provides you with a way to create :ref:`triggered events ` that are grouped together and only called once before the next frame. -.. |sched_once| replace:: `Clock.schedule_once `__ -.. |sched_intrvl| replace:: `Clock.schedule_interval `__ -.. |unsched| replace:: `Clock.unschedule `__ -.. |trigger| replace:: `Clock.create_trigger `__ +.. |sched_once| replace:: :meth:`~kivy.clock.ClockBase.schedule_once` +.. |sched_intrvl| replace:: :meth:`~kivy.clock.ClockBase.schedule_interval` +.. |unsched| replace:: :meth:`~kivy.clock.ClockBase.unschedule` +.. |trigger| replace:: :meth:`~kivy.clock.ClockBase.create_trigger` .. |urlreq| replace:: :class:`UrlRequest ` is useful to do asynchronous requests without blocking the event loop, and manage the result and progress with callbacks. +------------------+------------------+ diff --git a/doc/sources/gettingstarted/layouts.rst b/doc/sources/gettingstarted/layouts.rst index c6b3d6bc5..1d72b2a4b 100644 --- a/doc/sources/gettingstarted/layouts.rst +++ b/doc/sources/gettingstarted/layouts.rst @@ -10,6 +10,7 @@ Layouts are used to arrange widgets in a perticular manner. :: AnchorLayout: widgets can be anchored to 'top', 'bottom', 'left', 'right', 'center' BoxLayout: widgets are arranged in a box in either 'vertical' or 'horizontal' orientation FloatLayout: Widgets are essentially unrestricted + RelativeLayout: Child widgets are positioned relative to the layout. GridLayout: widgets are arranged in a grid defined by `rows` and `cols` properties StackLayout: widgets are stacked in `lr-tb` (left to right then top to bottom) or `tb-lr` order @@ -20,8 +21,9 @@ size_hint and pos_hint are used to calculate widget's size and position only if However one can set these to None and provide direct values in screen coordinates. For a detailed look at how you can arrange widgets using layouts look in -`AnchorLayout `_ -`BoxLayout `_ -`FloatLayout `_ -`GridLayout `_ -`StackLayout `_ +:mod:`AnchorLayout ` +:mod:`BoxLayout ` +:mod:`FloatLayout ` +:mod:`GridLayout ` +:mod:`StackLayout ` +:mod:`RelativeLayout ` diff --git a/doc/sources/gettingstarted/properties.rst b/doc/sources/gettingstarted/properties.rst index c76bd7fcc..7e2fc2cc0 100644 --- a/doc/sources/gettingstarted/properties.rst +++ b/doc/sources/gettingstarted/properties.rst @@ -33,15 +33,15 @@ provides an ``on_`` event that is called whenever the property's state/value changes . Kivy provides the following properties: - `NumericProperty `_, - `StringProperty `_, - `ListProperty `_, - `ObjectProperty `_, - `BooleanProperty `_, - `BoundedNumericProperty `_, - `OptionProperty `_, - `ReferenceListProperty `_, - `AliasProperty `_, - `DictProperty `_, + :mod:`~kivy.properties.NumericProperty`, + :mod:`~kivy.properties.StringProperty`, + :mod:`~kivy.properties.ListProperty`, + :mod:`~kivy.properties.ObjectProperty`, + :mod:`~kivy.properties.BooleanProperty`, + :mod:`~kivy.properties.BoundedNumericProperty`, + :mod:`~kivy.properties.OptionProperty`, + :mod:`~kivy.properties.ReferenceListProperty`, + :mod:`~kivy.properties.AliasProperty`, + :mod:`~kivy.properties.DictProperty`, For an in-depth explaination, look at :doc:`/api-kivy.properties` From b71e036f20cb82b15d187cc12ca7e9553f6bfe7b Mon Sep 17 00:00:00 2001 From: legikaloz Date: Tue, 24 Jul 2012 23:53:27 +0300 Subject: [PATCH 41/86] New property to keep raw image data. Useful to perform pixel based collision detection on the Image widget --- kivy/uix/image.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/kivy/uix/image.py b/kivy/uix/image.py index e798c8547..7dafa2f0b 100644 --- a/kivy/uix/image.py +++ b/kivy/uix/image.py @@ -136,6 +136,14 @@ class Image(Widget): :data:`keep_ratio` is a :class:`~kivy.properties.BooleanProperty`, default to True ''' + + keep_data = BooleanProperty(False) + '''If true the underlaying _coreimage have to keep the raw image data. Useful + to perform pixel based collision detection + + :data:`keep_ratio` is a :class:`~kivy.properties.BooleanProperty`, + default to False + ''' anim_delay = NumericProperty(.25) '''Delay of animation if the image is sequenced (like an animated gif). @@ -205,7 +213,7 @@ class Image(Widget): if self._coreimage is not None: self._coreimage.unbind(on_texture=self._on_tex_change) self._coreimage = ci = CoreImage(filename, mipmap=mipmap, - anim_delay=self.anim_delay) + anim_delay=self.anim_delay,keep_data=self.keep_data) ci.bind(on_texture=self._on_tex_change) self.texture = ci.texture From a9bfc5ec957344d20038d2979c27c6ecfab4996a Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Wed, 25 Jul 2012 00:21:37 +0200 Subject: [PATCH 42/86] fix doc/pep8 for new prop --- kivy/uix/image.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/kivy/uix/image.py b/kivy/uix/image.py index 7dafa2f0b..cacbabda7 100644 --- a/kivy/uix/image.py +++ b/kivy/uix/image.py @@ -136,13 +136,15 @@ class Image(Widget): :data:`keep_ratio` is a :class:`~kivy.properties.BooleanProperty`, default to True ''' - + keep_data = BooleanProperty(False) - '''If true the underlaying _coreimage have to keep the raw image data. Useful - to perform pixel based collision detection - - :data:`keep_ratio` is a :class:`~kivy.properties.BooleanProperty`, - default to False + '''If true the underlaying _coreimage have to keep the raw image data. + Useful to perform pixel based collision detection + + .. versionadded:: 1.3.0 + + :data:`keep_ratio` is a :class:`~kivy.properties.BooleanProperty`, default + to False ''' anim_delay = NumericProperty(.25) @@ -213,7 +215,7 @@ class Image(Widget): if self._coreimage is not None: self._coreimage.unbind(on_texture=self._on_tex_change) self._coreimage = ci = CoreImage(filename, mipmap=mipmap, - anim_delay=self.anim_delay,keep_data=self.keep_data) + anim_delay=self.anim_delay, keep_data=self.keep_data) ci.bind(on_texture=self._on_tex_change) self.texture = ci.texture From 278614d84a90c5b77501b514bbf6274788b5fc40 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Sun, 22 Jul 2012 08:08:33 -0700 Subject: [PATCH 43/86] - updated references of ' ::' to '::' where appropriate - made doc/Makefile call autodoc.py - doc warnings treated as errors --- doc/Makefile | 10 +++++++++- doc/README | 4 ++-- doc/sources/contribute.rst | 1 + doc/sources/gettingstarted/events.rst | 2 +- doc/sources/gettingstarted/layouts.rst | 2 +- doc/sources/guide/inputs.rst | 2 +- doc/sources/guide/layouts.rst | 5 +++-- doc/sources/guide/widgettree.rst | 2 +- doc/sources/installation/installation.rst | 2 +- doc/sources/sphinxext/preprocess.py | 2 +- kivy/__init__.py | 2 +- kivy/animation.py | 2 +- kivy/app.py | 2 +- kivy/base.py | 2 +- kivy/clock.py | 8 ++++---- kivy/core/clipboard/__init__.py | 4 ++-- kivy/core/image/__init__.py | 2 +- kivy/core/window/__init__.py | 2 +- kivy/graphics/compiler.pyx | 6 +++--- kivy/graphics/fbo.pyx | 2 +- kivy/graphics/transformation.pyx | 2 +- kivy/input/factory.py | 2 +- kivy/input/motionevent.py | 8 ++++---- kivy/input/postproc/dejitter.py | 2 +- kivy/input/postproc/doubletap.py | 2 +- kivy/input/postproc/ignorelist.py | 2 +- kivy/input/postproc/retaintouch.py | 2 +- kivy/input/providers/hidinput.py | 4 ++-- kivy/input/providers/linuxwacom.py | 2 +- kivy/input/providers/mouse.py | 4 ++-- kivy/input/providers/mtdev.py | 2 +- kivy/input/providers/probesysfs.py | 2 +- kivy/lang.py | 4 ++-- kivy/loader.py | 2 +- kivy/properties.pyx | 2 +- kivy/tools/pep8checker/pre-commit.githook | 2 +- kivy/uix/anchorlayout.py | 2 +- kivy/uix/button.py | 4 ++-- kivy/uix/camera.py | 4 ++-- kivy/uix/image.py | 8 ++++---- kivy/uix/label.py | 8 ++++---- kivy/uix/popup.py | 8 ++++---- kivy/uix/progressbar.py | 2 +- kivy/uix/scatter.py | 12 ++++++------ kivy/uix/screenmanager.py | 2 +- kivy/uix/scrollview.py | 2 +- kivy/uix/slider.py | 10 +++++----- kivy/uix/tabbedpanel.py | 2 +- kivy/uix/textinput.py | 12 ++++++------ kivy/uix/togglebutton.py | 2 +- kivy/uix/video.py | 4 ++-- kivy/uix/videoplayer.py | 2 +- kivy/utils.py | 6 +++--- 53 files changed, 104 insertions(+), 94 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index d61b2d8bd..b544e0670 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -2,7 +2,8 @@ # # You can set these variables from the command line. -SPHINXOPTS = +PYTHON = python +SPHINXOPTS = -W SPHINXBUILD = sphinx-build PAPER = @@ -28,12 +29,14 @@ clean: html: mkdir -p build/html build/doctrees + $(PYTHON) autobuild.py $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html @echo @echo "Build finished. The HTML pages are in build/html." gettext: mkdir -p build/html build/doctrees_gettext + $(PYTHON) autobuild.py $(SPHINXBUILD) -b gettext $(ALLSPHINXOPTSGT) build/gettext @echo @echo "Build finished. The Gettext pages are in build/gettext." @@ -41,6 +44,7 @@ gettext: pickle: mkdir -p build/pickle build/doctrees + $(PYTHON) autobuild.py $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) build/pickle @echo @echo "Build finished; now you can process the pickle files or run" @@ -51,6 +55,7 @@ web: pickle htmlhelp: mkdir -p build/htmlhelp build/doctrees + $(PYTHON) autobuild.py $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ @@ -58,6 +63,7 @@ htmlhelp: latex: mkdir -p build/latex build/doctrees + $(PYTHON) autobuild.py $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex @echo @echo "Build finished; the LaTeX files are in build/latex." @@ -66,12 +72,14 @@ latex: changes: mkdir -p build/changes build/doctrees + $(PYTHON) autobuild.py $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes @echo @echo "The overview file is in build/changes." linkcheck: mkdir -p build/linkcheck build/doctrees + $(PYTHON) autobuild.py $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ diff --git a/doc/README b/doc/README index 04b4ecda3..a65fa90ea 100644 --- a/doc/README +++ b/doc/README @@ -1,9 +1,9 @@ Kivy - Documentation ==================== -You can access to the API documentation on web : +You can access the API documentation on web : * last released version : http://kivy.org/docs/api - * trunk version, nightly updated : http://kivy.org/docs/api-trunk/ + * trunk version, updated nightly : http://kivy.org/docs/api-trunk/ How to build the documentation diff --git a/doc/sources/contribute.rst b/doc/sources/contribute.rst index 42f1c325b..39f2ab6d3 100644 --- a/doc/sources/contribute.rst +++ b/doc/sources/contribute.rst @@ -219,6 +219,7 @@ Will result in: .. note:: This new feature will likely blow your mind .. warning:: Please take a seat before trying this feature + """ diff --git a/doc/sources/gettingstarted/events.rst b/doc/sources/gettingstarted/events.rst index 01590b049..3cb7f8cff 100644 --- a/doc/sources/gettingstarted/events.rst +++ b/doc/sources/gettingstarted/events.rst @@ -57,7 +57,7 @@ Going further Another thing to note is that if you override an event, you become responsible for implementing all its behaviour previously handled by the base class. The -easiest way to do this is to call `super()`: :: +easiest way to do this is to call `super()`:: def on_touch_down(self, touch): if super(OurClassName, self).on_touch_down(touch): diff --git a/doc/sources/gettingstarted/layouts.rst b/doc/sources/gettingstarted/layouts.rst index 1d72b2a4b..ff8fc11e5 100644 --- a/doc/sources/gettingstarted/layouts.rst +++ b/doc/sources/gettingstarted/layouts.rst @@ -5,7 +5,7 @@ Layouts Arranging Your Widgets -Layouts are used to arrange widgets in a perticular manner. :: +Layouts are used to arrange widgets in a perticular manner:: AnchorLayout: widgets can be anchored to 'top', 'bottom', 'left', 'right', 'center' BoxLayout: widgets are arranged in a box in either 'vertical' or 'horizontal' orientation diff --git a/doc/sources/guide/inputs.rst b/doc/sources/guide/inputs.rst index a31ee4299..2f4cea1aa 100644 --- a/doc/sources/guide/inputs.rst +++ b/doc/sources/guide/inputs.rst @@ -2,7 +2,7 @@ Input management ================ Input architecture ------------------ +------------------ Kivy is able to handle most types of input: mouse, touchscreen, accelerometer, gyroscope, etc. It handles the native multitouch protocols on the following diff --git a/doc/sources/guide/layouts.rst b/doc/sources/guide/layouts.rst index d000dc1a5..987b37137 100644 --- a/doc/sources/guide/layouts.rst +++ b/doc/sources/guide/layouts.rst @@ -25,8 +25,9 @@ BoxLayout: .. image:: ../images/boxlayout.gif GridLayout: - Arrange widgets in a grid, you must specifiy at least one dimension of the - grid, so kivy can comput size of the elements and how to arrange them + Arrange widgets in a grid. You must specifiy at least one dimension of the + grid so kivy can compute the size of the elements and how to arrange them. + `pos_hint` not honored .. image:: ../images/gridlayout.gif diff --git a/doc/sources/guide/widgettree.rst b/doc/sources/guide/widgettree.rst index 1860b6088..61b39f077 100644 --- a/doc/sources/guide/widgettree.rst +++ b/doc/sources/guide/widgettree.rst @@ -54,7 +54,7 @@ Traversing the tree ------------------- The widget class has a :data:`~kivy.uix.widget.Widget.children` list property -that contains all the children. You can easily traverse the tree by doing :: +that contains all the children. You can easily traverse the tree by doing:: root = BoxLayout() # ... add widgets to root ... diff --git a/doc/sources/installation/installation.rst b/doc/sources/installation/installation.rst index e93954ced..16520c864 100644 --- a/doc/sources/installation/installation.rst +++ b/doc/sources/installation/installation.rst @@ -141,7 +141,7 @@ Uninstalling Kivy If you are mixing multiple Kivy installations, you might be confused about where each Kivy version is located. Please note that you might need to follow these steps multiple times, if you have multiple kivy versions installed in the Python library path. -To find your current installed version, you can use the command line: :: +To find your current installed version, you can use the command line:: $ python -c 'import kivy; print kivy.__path__' diff --git a/doc/sources/sphinxext/preprocess.py b/doc/sources/sphinxext/preprocess.py index e983d4b69..b7d1d5b5a 100644 --- a/doc/sources/sphinxext/preprocess.py +++ b/doc/sources/sphinxext/preprocess.py @@ -63,7 +63,7 @@ def callback_docstring(app, what, name, obj, options, lines): line = lines.pop(0) # trick to realign the first line to the second one. - # FIXME: fail if we finishing with :: + # FIXME: fail if we finishing with:: line_with_text = [x for x in lines if len(x.strip())] if len(line_with_text) and line is not None and len(lines): l = len(line_with_text[0]) - len(line_with_text[0].lstrip()) diff --git a/kivy/__init__.py b/kivy/__init__.py index c174f58ff..bd72ac442 100644 --- a/kivy/__init__.py +++ b/kivy/__init__.py @@ -143,7 +143,7 @@ def kivy_register_post_configuration(callback): def kivy_usage(): - '''Kivy Usage: %s [OPTION...] :: + '''Kivy Usage: %s [OPTION...]:: -h, --help Prints this help message. diff --git a/kivy/animation.py b/kivy/animation.py index df728e1d6..4270d0ab3 100644 --- a/kivy/animation.py +++ b/kivy/animation.py @@ -136,7 +136,7 @@ class Animation(EventDispatcher): '''Stop all animations that concern a specific widget / list of properties. - Example :: + Example:: anim = Animation(x=50) anim.start(widget) diff --git a/kivy/app.py b/kivy/app.py index d6cabb7de..330463742 100644 --- a/kivy/app.py +++ b/kivy/app.py @@ -309,7 +309,7 @@ class App(EventDispatcher): widget and added to the window. :return: None or a root :class:`~kivy.uix.widget.Widget` instance is no - self.root exist. + self.root exist. ''' if not self.root: return Widget() diff --git a/kivy/base.py b/kivy/base.py index 9e0cd746f..c25120fe4 100644 --- a/kivy/base.py +++ b/kivy/base.py @@ -25,7 +25,7 @@ EventLoop = None class ExceptionHandler: '''Base handler that catch exception in runTouchApp(). - You can derivate and use it like this :: + You can derivate and use it like this:: class E(ExceptionHandler): def handle_exception(self, inst): diff --git a/kivy/clock.py b/kivy/clock.py index e35a0cad8..37a8a3988 100644 --- a/kivy/clock.py +++ b/kivy/clock.py @@ -3,7 +3,7 @@ Clock object ============ The :class:`Clock` object allows you to schedule a function call in the -future; once or on interval. :: +future; once or on interval:: def my_callback(dt): pass @@ -93,7 +93,7 @@ Triggered Events A triggered event is a way to defer a callback exactly like schedule_once(), but with some added convenience. The callback will only be scheduled once per frame, even if you call the trigger twice (or more). This is not the case -with :func:`Clock.schedule_once` :: +with :func:`Clock.schedule_once`:: # will run the callback twice before the next frame Clock.schedule_once(my_callback) @@ -104,7 +104,7 @@ with :func:`Clock.schedule_once` :: t() t() -Before triggered events, you may have used this approach in a widget :: +Before triggered events, you may have used this approach in a widget:: def trigger_callback(self, *largs): Clock.unschedule(self.callback) @@ -112,7 +112,7 @@ Before triggered events, you may have used this approach in a widget :: As soon as you call `trigger_callback()`, it will correctly schedule the callback once in the next frame. It is more convenient to create and bind to -the triggered event than using :func:`Clock.schedule_once` in a function :: +the triggered event than using :func:`Clock.schedule_once` in a function:: from kivy.clock import Clock from kivy.uix.widget import Widget diff --git a/kivy/core/clipboard/__init__.py b/kivy/core/clipboard/__init__.py index ac9954211..a3bf72c7a 100644 --- a/kivy/core/clipboard/__init__.py +++ b/kivy/core/clipboard/__init__.py @@ -20,8 +20,8 @@ Usage example:: >>> Clipboard.get('UTF8_STRING') 'Great' -.. note:: the main implementation rely on Pygame, and works great with -text/string. Anything else might not work the same on all platform. +.. note:: The main implementation rely on Pygame, and works great with + text/string. Anything else might not work the same on all platform. ''' __all__ = ('ClipboardBase', 'Clipboard') diff --git a/kivy/core/image/__init__.py b/kivy/core/image/__init__.py index 61e97b852..56759cf91 100644 --- a/kivy/core/image/__init__.py +++ b/kivy/core/image/__init__.py @@ -623,7 +623,7 @@ class Image(EventDispatcher): .. warning:: This function can be used only with images loaded with - keep_data=True keyword. For examples :: + keep_data=True keyword. For examples:: m = Image.load('image.png', keep_data=True) color = m.read_pixel(150, 150) diff --git a/kivy/core/window/__init__.py b/kivy/core/window/__init__.py index 1e300e85f..38aed8ba3 100755 --- a/kivy/core/window/__init__.py +++ b/kivy/core/window/__init__.py @@ -286,7 +286,7 @@ class WindowBase(EventDispatcher): bind=('_clearcolor', )) '''Color used to clear window. - :: + :: from kivy.core.window import Window # red background color diff --git a/kivy/graphics/compiler.pyx b/kivy/graphics/compiler.pyx index cb5f8b39f..c53d7987f 100644 --- a/kivy/graphics/compiler.pyx +++ b/kivy/graphics/compiler.pyx @@ -9,7 +9,7 @@ at rendering time. Reducing the context instructions --------------------------------- -Imagine that you have a scheme like this :: +Imagine that you have a scheme like this:: Color(1, 1, 1) Rectangle(source='button.png', pos=(0, 0), size=(20, 20)) @@ -18,7 +18,7 @@ Imagine that you have a scheme like this :: Color(1, 1, 1) Rectangle(source='button.png', pos=(10, 20), size=(20, 20)) -The real instruction seen by the graphics canvas would be :: +The real instruction seen by the graphics canvas would be:: Color: change 'color' context to 1, 1, 1 BindTexture: change 'texture0' to `button.png texture` @@ -32,7 +32,7 @@ The real instruction seen by the graphics canvas would be :: Only the first :class:`~kivy.graphics.context_instructions.Color` and :class:`~kivy.graphics.context_instructions.BindTexture` are useful, and really -change the context. We can reduce them to :: +change the context. We can reduce them to:: Color: change 'color' context to 1, 1, 1 BindTexture: change 'texture0' to `button.png texture` diff --git a/kivy/graphics/fbo.pyx b/kivy/graphics/fbo.pyx index 74e0ef917..76e68b222 100644 --- a/kivy/graphics/fbo.pyx +++ b/kivy/graphics/fbo.pyx @@ -7,7 +7,7 @@ texture, and use your fbo as a texture for another drawing. Fbo act as a :class:`kivy.graphics.instructions.Canvas`. -Exemple of using an fbo for some color rectangles :: +Example of using an fbo for some color rectangles:: from kivy.graphics import Fbo, Color, Rectangle diff --git a/kivy/graphics/transformation.pyx b/kivy/graphics/transformation.pyx index 381d5d377..75cb1b04e 100644 --- a/kivy/graphics/transformation.pyx +++ b/kivy/graphics/transformation.pyx @@ -29,7 +29,7 @@ cdef extern from "string.h": cdef double _EPS = 8.8817841970012523e-16 cdef class Matrix: - '''Optimized matrix class for OpenGL :: + '''Optimized matrix class for OpenGL:: >>> from kivy.graphics.transformation import Matrix >>> m = Matrix() diff --git a/kivy/input/factory.py b/kivy/input/factory.py index 82e1ec9fa..e8e50e5bc 100644 --- a/kivy/input/factory.py +++ b/kivy/input/factory.py @@ -11,7 +11,7 @@ __all__ = ('MotionEventFactory', ) class MotionEventFactory: '''MotionEvent factory is a class who register all availables input factories. If you create a new input factory, don't forget to register it - :: + :: MotionEventFactory.register('myproviderid', MyInputProvider) diff --git a/kivy/input/motionevent.py b/kivy/input/motionevent.py index 41084be0b..3f2460f40 100644 --- a/kivy/input/motionevent.py +++ b/kivy/input/motionevent.py @@ -30,7 +30,7 @@ Listen to Motion Event ---------------------- If you want to receive all Motion Event, Touch or not, you can bind motion event -from :class:`~kivy.core.window.Window` to your own callbacks :: +from :class:`~kivy.core.window.Window` to your own callbacks:: def on_motion(self, etype, motionevent): # will receive all motion event. @@ -64,13 +64,13 @@ pressure Pressure of the contact. Use property `pressure` shape Contact shape. Use property `shape` ============== ================================================================ -If yo want to know if the current :class:`MotionEvent` have an angle :: +If yo want to know if the current :class:`MotionEvent` have an angle:: def on_touch_move(self, touch): if 'angle' in touch.profile: print 'The touch angle is', touch.a -If you want to select only the fiducials :: +If you want to select only the fiducials:: def on_touch_move(self, touch): if 'markerid' not in touch.profile: @@ -276,7 +276,7 @@ class MotionEvent(object): def grab(self, class_instance, exclusive=False): '''Grab this motion event. You can grab a touch if you absolutly want to receive on_touch_move() and on_touch_up(), even if the touch is not - dispatched by your parent :: + dispatched by your parent:: def on_touch_down(self, touch): touch.grab(self) diff --git a/kivy/input/postproc/dejitter.py b/kivy/input/postproc/dejitter.py index 63fbdb21d..3cb3febf2 100644 --- a/kivy/input/postproc/dejitter.py +++ b/kivy/input/postproc/dejitter.py @@ -20,7 +20,7 @@ from kivy.config import Config class InputPostprocDejitter(object): ''' Get rid of jitterish BLOBs. - Example :: + Example:: [postproc] jitter_distance = 0.004 diff --git a/kivy/input/postproc/doubletap.py b/kivy/input/postproc/doubletap.py index d1292125d..280db0b10 100644 --- a/kivy/input/postproc/doubletap.py +++ b/kivy/input/postproc/doubletap.py @@ -16,7 +16,7 @@ class InputPostprocDoubleTap(object): ''' InputPostProcDoubleTap is a post-processor to check if a touch is a double tap or not. - Double tap can be configured in the Kivy config file :: + Double tap can be configured in the Kivy config file:: [postproc] double_tap_time = 250 diff --git a/kivy/input/postproc/ignorelist.py b/kivy/input/postproc/ignorelist.py index 2e691c081..6997b04a1 100644 --- a/kivy/input/postproc/ignorelist.py +++ b/kivy/input/postproc/ignorelist.py @@ -14,7 +14,7 @@ from kivy.utils import strtotuple class InputPostprocIgnoreList(object): ''' InputPostprocIgnoreList is a post-processor who remove touch in ignore list. - Ignore list can be configured in the Kivy config file :: + Ignore list can be configured in the Kivy config file:: [postproc] # Format: [(xmin, ymin, xmax, ymax), ...] diff --git a/kivy/input/postproc/retaintouch.py b/kivy/input/postproc/retaintouch.py index 8fed551d8..be9e31759 100644 --- a/kivy/input/postproc/retaintouch.py +++ b/kivy/input/postproc/retaintouch.py @@ -18,7 +18,7 @@ class InputPostprocRetainTouch(object): touch, to reuse it under certains conditions. This module is designed to prevent finger lost on some hardware/setup. - Retain touch can be configured in the Kivy config file :: + Retain touch can be configured in the Kivy config file:: [postproc] retain_time = 100 diff --git a/kivy/input/providers/hidinput.py b/kivy/input/providers/hidinput.py index b4aa2b8c1..e6ee0a55d 100644 --- a/kivy/input/providers/hidinput.py +++ b/kivy/input/providers/hidinput.py @@ -4,7 +4,7 @@ Native support of HID input from linux kernel Support start from 2.6.32-ubuntu, or 2.6.34. -To configure HIDInput, put in your configuration :: +To configure HIDInput, put in your configuration:: [input] # devicename = hidinput,/dev/input/eventXX @@ -29,7 +29,7 @@ To fix that, you can add one of theses options on the argument line : For example, on Asus T101M, the touchscreen report a range from 0-4095 for X and Y value, but real value are in a range from 0-32768. You can put it on -configuration :: +configuration:: [input] t101m = hidinput,/dev/input/event7,max_position_x=32768,max_position_y=32768 diff --git a/kivy/input/providers/linuxwacom.py b/kivy/input/providers/linuxwacom.py index f147b6ba2..ae9b17c0e 100644 --- a/kivy/input/providers/linuxwacom.py +++ b/kivy/input/providers/linuxwacom.py @@ -2,7 +2,7 @@ Native support of Wacom tablet from linuxwacom driver ===================================================== -To configure LinuxWacom, put in your configuration :: +To configure LinuxWacom, put in your configuration:: [input] pen = linuxwacom,/dev/input/event2,mode=pen diff --git a/kivy/input/providers/mouse.py b/kivy/input/providers/mouse.py index 48b4dce6e..bb9c45da3 100644 --- a/kivy/input/providers/mouse.py +++ b/kivy/input/providers/mouse.py @@ -8,7 +8,7 @@ touch can generate one event from mouse provider and from multitouch provider. To avoid this behavior, you can activate the "disable_on_activity" token in mouse. Then, if they are any touch active from another provider, the mouse will -be discarded. Put in your configuration :: +be discarded. Put in your configuration:: [input] mouse = mouse,disable_on_activity @@ -20,7 +20,7 @@ Disabling multitouch interaction with mouse By default middle and right mouse buttons ared used for multitouch emulation. If you want to use them for other purpose you can disable this behavior by -activating the "disable_multitouch" token :: +activating the "disable_multitouch" token:: [input] mouse = mouse,disable_multitouch diff --git a/kivy/input/providers/mtdev.py b/kivy/input/providers/mtdev.py index 819c55727..c7531644a 100644 --- a/kivy/input/providers/mtdev.py +++ b/kivy/input/providers/mtdev.py @@ -8,7 +8,7 @@ You can read more on http://wiki.ubuntu.com/Multitouch To configure MTDev, it's preferable to use probesysfs providers. Check :py:class:`~kivy.input.providers.probesysfs` for more information. -Otherwise, you can put in your configuration :: +Otherwise, you can put in your configuration:: [input] # devicename = hidinput,/dev/input/eventXX diff --git a/kivy/input/providers/probesysfs.py b/kivy/input/providers/probesysfs.py index 1125ce284..4fa055b0f 100644 --- a/kivy/input/providers/probesysfs.py +++ b/kivy/input/providers/probesysfs.py @@ -9,7 +9,7 @@ be made by other providers like: hidinput, mtdev, linuxwacom. mtdev is used prior to other providers. For more information about mtdev, check :py:class:`~kivy.input.providers.mtdev`. -Here is an example of auto creation :: +Here is an example of auto creation:: [input] # using mtdev diff --git a/kivy/lang.py b/kivy/lang.py index c3ebfc7d6..16b6bef05 100644 --- a/kivy/lang.py +++ b/kivy/lang.py @@ -265,7 +265,7 @@ For example, for a list, you'll need to create a entry with a image on the left, and a label on the right. You can create a template for making that definition more easy to use. So, we'll create a template that require 2 entry in the context: a image -filename and a title :: +filename and a title:: [IconItem@BoxLayout]: Image: @@ -275,7 +275,7 @@ filename and a title :: .. highlight:: python -Then in Python, you can create instanciate the template with :: +Then in Python, you can create instanciate the template with:: from kivy.lang import Builder diff --git a/kivy/loader.py b/kivy/loader.py index 1ef061992..5b5e225c9 100644 --- a/kivy/loader.py +++ b/kivy/loader.py @@ -206,7 +206,7 @@ class LoaderBase(object): '''Load a image using loader. A Proxy image is returned with a loading image. - :: + :: img = Loader.image(filename) # img will be a ProxyImage. # You'll use it the same as an Image class. diff --git a/kivy/properties.pyx b/kivy/properties.pyx index 3ad44534b..6ba56e704 100644 --- a/kivy/properties.pyx +++ b/kivy/properties.pyx @@ -835,7 +835,7 @@ cdef class AliasProperty(Property): If you didn't find a Property class that fits to your needs, you can still create Python getters and setters and create a property with both of them. - Example from kivy/uix/widget.py :: + Example from kivy/uix/widget.py:: def get_right(self): return self.x + self.width diff --git a/kivy/tools/pep8checker/pre-commit.githook b/kivy/tools/pep8checker/pre-commit.githook index d66034b1e..0681f48bd 100755 --- a/kivy/tools/pep8checker/pre-commit.githook +++ b/kivy/tools/pep8checker/pre-commit.githook @@ -12,7 +12,7 @@ the styleguide checker over your code and abort the commit if there are any errors. If that happens, please fix & retry. - To install :: + To install:: cp kivy/tools/pep8checker/pre-commit.githook .git/hooks/pre-commit chmod +x .git/hooks/pre-commit diff --git a/kivy/uix/anchorlayout.py b/kivy/uix/anchorlayout.py index e4c81ed4c..11e22ce56 100644 --- a/kivy/uix/anchorlayout.py +++ b/kivy/uix/anchorlayout.py @@ -16,7 +16,7 @@ Anchor Layout or center. -To draw a button in the lower-right corner :: +To draw a button in the lower-right corner:: layout = AnchorLayout( anchor_x='right', anchor_y='bottom') diff --git a/kivy/uix/button.py b/kivy/uix/button.py index 4c905e13d..1569246e2 100644 --- a/kivy/uix/button.py +++ b/kivy/uix/button.py @@ -13,7 +13,7 @@ the Label class:: button = Button(text='Hello world', font_size=14) To attach a callback when the button is pressed (clicked/touched), use -:class:`~kivy.uix.widget.Widget.bind` :: +:class:`~kivy.uix.widget.Widget.bind`:: def callback(instance): print 'The button <%s> is being pressed' % instance.text @@ -24,7 +24,7 @@ To attach a callback when the button is pressed (clicked/touched), use btn2.bind(on_press=callback) If you want to be notified every time the button state changes, you can attach -to the :data:`Button.state` property :: +to the :data:`Button.state` property:: def callback(instance, value): print 'My button <%s> state is <%s>' % (instance, value) diff --git a/kivy/uix/camera.py b/kivy/uix/camera.py index b836dfd73..81eb5dfb9 100644 --- a/kivy/uix/camera.py +++ b/kivy/uix/camera.py @@ -40,7 +40,7 @@ class Camera(Image): play = BooleanProperty(True) '''Boolean indicate if the camera is playing. - You can start/stop the camera by setting this property. :: + You can start/stop the camera by setting this property:: # start the camera playing at creation (default) cam = Camera(play=True) @@ -63,7 +63,7 @@ class Camera(Image): resolution = ListProperty([-1, -1]) '''Preferred resolution to use when invoking the camera. If you are using - [-1, -1], the resolution will be the default one. :: + [-1, -1], the resolution will be the default one:: # create a camera object with the best image available cam = Camera() diff --git a/kivy/uix/image.py b/kivy/uix/image.py index cacbabda7..7abbac3fb 100644 --- a/kivy/uix/image.py +++ b/kivy/uix/image.py @@ -2,7 +2,7 @@ Image ===== -The :class:`Image` widget is used to display an image. :: +The :class:`Image` widget is used to display an image:: wimg = Image(source='mylogo.png') @@ -10,7 +10,7 @@ Asynchronous Loading -------------------- To load an image asynchronously (for example from an external webserver), use -the :class:`AsyncImage` subclass :: +the :class:`AsyncImage` subclass:: aimg = AsyncImage(source='http://mywebsite.com/logo.png') @@ -21,12 +21,12 @@ By default, the image is centered and fit inside the widget bounding box. If you don't want that, you can inherit from Image and create your own style. For example, if you want your image to take the same size of your widget, you -can do :: +can do:: class FullImage(Image): pass -And in your kivy language file, you can do :: +And in your kivy language file, you can do:: : canvas: diff --git a/kivy/uix/label.py b/kivy/uix/label.py index 8803223fd..2e1603998 100644 --- a/kivy/uix/label.py +++ b/kivy/uix/label.py @@ -3,7 +3,7 @@ Label ===== The :class:`Label` widget is for rendering text. It supports ascii and unicode -strings :: +strings:: # hello world text l = Label(text='Hello world') @@ -211,11 +211,11 @@ class Label(Widget): text = StringProperty('') '''Text of the label. - Creation of a simple hello world :: + Creation of a simple hello world:: widget = Label(text='Hello world') - If you want to create the widget with an unicode string, use :: + If you want to create the widget with an unicode string, use:: widget = Label(text=u'My unicode string') @@ -365,7 +365,7 @@ class Label(Widget): The :data:`texture` update is scheduled for the next frame. If you need the texture immediately after changing a property, you have to call - the :func:`texture_update` function before accessing :data:`texture` :: + the :func:`texture_update` function before accessing :data:`texture`:: l = Label(text='Hello world') # l.texture is good diff --git a/kivy/uix/popup.py b/kivy/uix/popup.py index 5cbad720c..1d5dfcc8d 100644 --- a/kivy/uix/popup.py +++ b/kivy/uix/popup.py @@ -41,7 +41,7 @@ To manually dismiss/close the popup, use :meth:`Popup.dismiss`:: popup.dismiss() The :meth:`Popup.open` and :meth:`Popup.dismiss` are bindable. That means you -can directly bind the function to an action, e.g., to a button's on_press :: +can directly bind the function to an action, e.g., to a button's on_press:: # create content and assign to the popup content = Button(text='Close me!') @@ -59,7 +59,7 @@ Popup Events There are two events available: `on_open` when the popup is opening, and `on_dismiss` when it is closed. For `on_dismiss`, you can prevent the -popup from closing by explictly returning True from your callback :: +popup from closing by explictly returning True from your callback:: def my_callback(instance): print 'Popup', instance, 'is being dismissed, but is prevented!' @@ -73,8 +73,8 @@ popup from closing by explictly returning True from your callback :: __all__ = ('Popup', 'PopupException') from kivy.uix.modalview import ModalView -from kivy.properties import StringProperty, ObjectProperty, \ - NumericProperty, ListProperty +from kivy.properties import (StringProperty, ObjectProperty, + NumericProperty, ListProperty) class PopupException(Exception): diff --git a/kivy/uix/progressbar.py b/kivy/uix/progressbar.py index 943348f92..f7ef59be0 100644 --- a/kivy/uix/progressbar.py +++ b/kivy/uix/progressbar.py @@ -12,7 +12,7 @@ Only horizontal mode is supported, vertical mode is not available yet. The progress bar has no interactive elements, It is a display-only widget. -To use it, simply assign a value to indicate the current progress :: +To use it, simply assign a value to indicate the current progress:: from kivy.uix.progressbar import ProgressBar pb = ProgressBar(max=1000) diff --git a/kivy/uix/scatter.py b/kivy/uix/scatter.py index a431b1fae..ebd86a8fe 100644 --- a/kivy/uix/scatter.py +++ b/kivy/uix/scatter.py @@ -29,7 +29,7 @@ Usage By default, the widget does not have a graphical representation. It is a container only. The idea is to combine Scatter with another widget, for -example :class:`~kivy.uix.image.Image` :: +example :class:`~kivy.uix.image.Image`:: scatter = Scatter() image = Image(source='sun.jpg') @@ -41,15 +41,15 @@ Control Interactions By default, all interactions are enabled. You can selectively disable them using the do_{rotation, translation, scale} properties. -Disable rotation :: +Disable rotation:: scatter = Scatter(do_rotation=False) -Allow only translation :: +Allow only translation:: scatter = Scatter(do_rotation=False, do_scale=False) -Allow only translation on x axis :: +Allow only translation on x axis:: scatter = Scatter(do_rotation=False, do_scale=False, do_translation_y=False) @@ -72,7 +72,7 @@ a limit for scaling. You cannot do infinite scale down/up with our implementation. Generally, you don't hit the minimum scale (because you don't see it on the screen), but the maximum scale is 9.99506983235e+19 (2^66). -You can also limit the minimum and maximum scale allowed. :: +You can also limit the minimum and maximum scale allowed:: scatter = Scatter(scale_min=.5, scale_max=3.) @@ -203,7 +203,7 @@ class Scatter(Widget): return (xmin, ymin), (xmax-xmin, ymax-ymin) bbox = AliasProperty(_get_bbox, None, bind=( 'transform', 'width', 'height')) - '''Bounding box of the widget in parent space. :: + '''Bounding box of the widget in parent space:: ((x, y), (w, h)) # x, y = lower left corner diff --git a/kivy/uix/screenmanager.py b/kivy/uix/screenmanager.py index 1d5ecf39b..27f038290 100644 --- a/kivy/uix/screenmanager.py +++ b/kivy/uix/screenmanager.py @@ -503,7 +503,7 @@ class ScreenManager(FloatLayout): current = StringProperty(None) '''Name of the screen currently show, or the screen to show. - :: + :: from kivy.uix.screenmanager import ScreenManager, Screen diff --git a/kivy/uix/scrollview.py b/kivy/uix/scrollview.py index 4fcef19ad..00ff6d0db 100644 --- a/kivy/uix/scrollview.py +++ b/kivy/uix/scrollview.py @@ -50,7 +50,7 @@ the size_hint instructions (x or y) of the child to enable scrolling. To scroll a :class:`GridLayout` on Y-axis/vertically, set the child's width identical to that of the ScrollView (size_hint_x=1, default), and set the -size_hint_y property to None :: +size_hint_y property to None:: layout = GridLayout(cols=1, spacing=10, size_hint_y=None) #Make sure the height is such that there is something to scroll. diff --git a/kivy/uix/slider.py b/kivy/uix/slider.py index cd3693dfd..90e31f660 100644 --- a/kivy/uix/slider.py +++ b/kivy/uix/slider.py @@ -7,12 +7,12 @@ Slider The :class:`Slider` widget looks like a scrollbar. It supports horizontal and vertical orientation, min/max and a default value. -To create a slider from -100 to 100 starting at 25 :: +To create a slider from -100 to 100 starting at 25:: from kivy.uix.slider import Slider s = Slider(min=-100, max=100, value=25) -To create a vertical slider :: +To create a vertical slider:: from kivy.uix.slider import Slider s = Slider(orientation='vertical') @@ -71,7 +71,7 @@ class Slider(Widget): ''' range = ReferenceListProperty(min, max) - '''Range of the slider, in the format (minimum value, maximum value). :: + '''Range of the slider, in the format (minimum value, maximum value):: >>> slider = Slider(min=10, max=80) >>> slider.range @@ -98,7 +98,7 @@ class Slider(Widget): self.value = value * (self.max - vmin) + vmin value_normalized = AliasProperty(get_norm_value, set_norm_value, bind=('value', 'min', 'max')) - '''Normalized value inside the :data:`range` (min/max) to 0-1 range. :: + '''Normalized value inside the :data:`range` (min/max) to 0-1 range:: >>> slider = Slider(value=50, min=0, max=100) >>> slider.value @@ -113,7 +113,7 @@ class Slider(Widget): 1 You can also use it for setting the real value without knowing the minimum - and maximum. :: + and maximum:: >>> slider = Slider(min=0, max=200) >>> slider.value_normalized = .5 diff --git a/kivy/uix/tabbedpanel.py b/kivy/uix/tabbedpanel.py index e39d9fd9f..fd2caac56 100644 --- a/kivy/uix/tabbedpanel.py +++ b/kivy/uix/tabbedpanel.py @@ -20,7 +20,7 @@ The :class:`TabbedPanel` provides one default tab. Simple example -------------- -.. include :: ../../examples/widgets/tabbedpanel.py +.. include:: ../../examples/widgets/tabbedpanel.py :literal: Customize the Tabbed Panel diff --git a/kivy/uix/textinput.py b/kivy/uix/textinput.py index 4ecc6d672..a47585d95 100644 --- a/kivy/uix/textinput.py +++ b/kivy/uix/textinput.py @@ -30,7 +30,7 @@ To create a multiline textinput ('enter' key adds a new line):: textinput = TextInput(text='Hello world') To create a monoline textinput, set the multiline property to false ('enter' -key will defocus the textinput and emit on_text_validate event) :: +key will defocus the textinput and emit on_text_validate event):: def on_enter(instance, value): print 'User pressed enter in', instance @@ -38,7 +38,7 @@ key will defocus the textinput and emit on_text_validate event) :: textinput = TextInput(text='Hello world', multiline=False) textinput.bind(on_text_validate=on_enter) -To run a callback when the text changes :: +To run a callback when the text changes:: def on_text(instance, value): print 'The widget', instance, 'have:', value @@ -47,13 +47,13 @@ To run a callback when the text changes :: textinput.bind(text=on_text) You can 'focus' a textinput, meaning that the input box will be highlighted, -and keyboard focus will be requested :: +and keyboard focus will be requested:: textinput = TextInput(focus=True) The textinput is defocused if the 'escape' key is pressed, or if another widget requests the keyboard. You can bind a callback to the focus property to -get notified of focus changes :: +get notified of focus changes:: def on_focus(instance, value): if value: @@ -1437,11 +1437,11 @@ class TextInput(Widget): text = AliasProperty(_get_text, _set_text, bind=('_lines', )) '''Text of the widget. - Creation of a simple hello world :: + Creation of a simple hello world:: widget = TextInput(text='Hello world') - If you want to create the widget with an unicode string, use :: + If you want to create the widget with an unicode string, use:: widget = TextInput(text=u'My unicode string') diff --git a/kivy/uix/togglebutton.py b/kivy/uix/togglebutton.py index f5db3a677..88d1197a5 100644 --- a/kivy/uix/togglebutton.py +++ b/kivy/uix/togglebutton.py @@ -8,7 +8,7 @@ that is only 'down' as long as it is pressed). Toggle buttons can also be grouped to make radio buttons - only one button in a group can be in 'down' state. The group name can be a string or any other -hashable Python object :: +hashable Python object:: btn1 = ToggleButton(text='Male', group='sex',) btn2 = ToggleButton(text='Female', group='sex', state='down') diff --git a/kivy/uix/video.py b/kivy/uix/video.py index 7b8198543..5c30ae9ee 100644 --- a/kivy/uix/video.py +++ b/kivy/uix/video.py @@ -11,7 +11,7 @@ are installed). Our :class:`~kivy.core.video.VideoBase` implementation is used under the hood. Video loading is asynchronous - many properties are not available until -the video is loaded (when the texture is created). :: +the video is loaded (when the texture is created):: def on_position_change(instance, value): print 'The position in the video is', value @@ -38,7 +38,7 @@ class Video(Image): play = BooleanProperty(False) '''Boolean, indicates if the video is playing. - You can start/stop the video by setting this property. :: + You can start/stop the video by setting this property:: # start playing the video at creation video = Video(source='movie.mkv', play=True) diff --git a/kivy/uix/videoplayer.py b/kivy/uix/videoplayer.py index 3ecb51076..85ecf2b82 100644 --- a/kivy/uix/videoplayer.py +++ b/kivy/uix/videoplayer.py @@ -288,7 +288,7 @@ class VideoPlayer(GridLayout): play = BooleanProperty(False) '''Boolean, indicates if the video is playing. - You can start/stop the video by setting this property. :: + You can start/stop the video by setting this property:: # start playing the video at creation video = VideoPlayer(source='movie.mkv', play=True) diff --git a/kivy/utils.py b/kivy/utils.py index ed97f5cdd..2af0fda4c 100644 --- a/kivy/utils.py +++ b/kivy/utils.py @@ -36,7 +36,7 @@ def difference(set1, set2): def interpolate(value_from, value_to, step=10): '''Interpolate a value to another. Can be useful to smooth some transition. - For example :: + For example:: # instead of setting directly self.pos = pos @@ -60,7 +60,7 @@ def interpolate(value_from, value_to, step=10): def strtotuple(s): '''Convert a tuple string into tuple, with some security check. Designed to be used - with eval() function :: + with eval() function:: a = (12, 54, 68) b = str(a) # return '(12, 54, 68)' @@ -271,7 +271,7 @@ class QueryDict(dict): .. versionadded:: 1.0.4 - :: + :: d = QueryDict() # create a key named toto, with the value 1 From 7c83a07601b37c1e50674bcc97f7b14826d49c89 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Sun, 22 Jul 2012 23:38:51 -0500 Subject: [PATCH 44/86] - more documentation formatting corrections --- kivy/__init__.py | 11 +++++++---- kivy/core/window/__init__.py | 15 +++++++++------ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/kivy/__init__.py b/kivy/__init__.py index bd72ac442..cf1f3a60f 100644 --- a/kivy/__init__.py +++ b/kivy/__init__.py @@ -24,7 +24,7 @@ __all__ = ( 'kivy_configure', 'kivy_register_post_configuration', 'kivy_options', 'kivy_base_dir', 'kivy_modules_dir', 'kivy_data_dir', 'kivy_shader_dir', - 'kivy_icons_dir', 'kivy_home_dir', + 'kivy_icons_dir', 'kivy_home_dir', 'kivy_userexts_dir', 'kivy_config_fn', 'kivy_usermodules_dir', ) @@ -224,11 +224,14 @@ kivy_shader_dir = join(kivy_data_dir, 'glsl') #: Kivy icons config path (don't remove the last '') kivy_icons_dir = join(kivy_data_dir, 'icons', '') #: Kivy user-home storage directory -kivy_home_dir = None +kivy_home_dir = '' #: Kivy configuration filename -kivy_config_fn = None +kivy_config_fn = '' #: Kivy user modules directory -kivy_usermodules_dir = None +kivy_usermodules_dir = '' +#: Kivy user extensions directory +kivy_userexts_dir = '' + # Don't go further if we generate documentation if basename(sys.argv[0]) in ('sphinx-build', 'autobuild.py'): diff --git a/kivy/core/window/__init__.py b/kivy/core/window/__init__.py index 38aed8ba3..1c5f15aaa 100755 --- a/kivy/core/window/__init__.py +++ b/kivy/core/window/__init__.py @@ -194,18 +194,21 @@ class WindowBase(EventDispatcher): `on_keyboard`: key, scancode, codepoint, modifier Fired when the keyboard is in action .. versionchanged:: 1.3.0 - The *unicode* parameter has be deprecated in favor of - codepoint, and will be removed completely in future versions + + The *unicode* parameter has be deprecated in favor of + codepoint, and will be removed completely in future versions `on_key_down`: key, scancode, codepoint Fired when a key is down .. versionchanged:: 1.3.0 - The *unicode* parameter has be deprecated in favor of - codepoint, and will be removed completely in future versions + + The *unicode* parameter has be deprecated in favor of + codepoint, and will be removed completely in future versions `on_key_up`: key, scancode, codepoint Fired when a key is up .. versionchanged:: 1.3.0 - The *unicode* parameter has be deprecated in favor of - codepoint, and will be removed completely in future versions + + The *unicode* parameter has be deprecated in favor of + codepoint, and will be removed completely in future versions `on_dropfile`: str Fired when a file is dropped on the application ''' From a839690981e2c3fbd3d83d2215941c9eec828989 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Mon, 23 Jul 2012 21:20:59 -0500 Subject: [PATCH 45/86] - updated readme --- doc/README | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/doc/README b/doc/README index a65fa90ea..5af6ddb43 100644 --- a/doc/README +++ b/doc/README @@ -13,10 +13,7 @@ You need to install : * Python Sphinx (apt-get install python-sphinx) * Latest kivy -Run autobuild.py : - python autobuild.py - -And generate documentation +Generate documentation using make:: make html Documentation will be accessible in build/html/ From 60c9b0db802d5fe92a39aae363f7cac8ca54c551 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Mon, 23 Jul 2012 21:39:27 -0500 Subject: [PATCH 46/86] - transformation no longer raising indentation errors --- kivy/graphics/transformation.pyx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kivy/graphics/transformation.pyx b/kivy/graphics/transformation.pyx index 75cb1b04e..230833b37 100644 --- a/kivy/graphics/transformation.pyx +++ b/kivy/graphics/transformation.pyx @@ -29,7 +29,8 @@ cdef extern from "string.h": cdef double _EPS = 8.8817841970012523e-16 cdef class Matrix: - '''Optimized matrix class for OpenGL:: + ''' + Optimized matrix class for OpenGL:: >>> from kivy.graphics.transformation import Matrix >>> m = Matrix() @@ -42,7 +43,7 @@ cdef class Matrix: [ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11] - [12 13 14 15] + [ 12 13 14 15] ''' From e17f65e617e582287d287c558e0acb2df343ea00 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Mon, 23 Jul 2012 23:02:22 -0500 Subject: [PATCH 47/86] - made logic for testing environ variables more accurate - kivy more robust when checking for build scripts --- kivy/__init__.py | 9 +++++---- kivy/config.py | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/kivy/__init__.py b/kivy/__init__.py index cf1f3a60f..53592a838 100644 --- a/kivy/__init__.py +++ b/kivy/__init__.py @@ -234,13 +234,14 @@ kivy_userexts_dir = '' # Don't go further if we generate documentation -if basename(sys.argv[0]) in ('sphinx-build', 'autobuild.py'): +if any(name in sys.argv[0] for name in ('sphinx-build', 'autobuild.py')): environ['KIVY_DOC'] = '1' -if basename(sys.argv[0]) in ('sphinx-build', ): +if 'sphinx-build' in sys.argv[0]: environ['KIVY_DOC_INCLUDE'] = '1' -if basename(sys.argv[0]) in ('nosetests', ) or 'nosetests' in sys.argv: +if any('nosetests' in arg for arg in sys.argv): environ['KIVY_UNITTEST'] = '1' -if not 'KIVY_DOC_INCLUDE' in environ: + +if not environ.get('KIVY_DOC_INCLUDE'): # Configuration management user_home_dir = expanduser('~') if platform() == 'android': diff --git a/kivy/config.py b/kivy/config.py index 1c7280222..d1b20e5e9 100644 --- a/kivy/config.py +++ b/kivy/config.py @@ -255,7 +255,7 @@ class ConfigParser(PythonConfigParser): return True -if not 'KIVY_DOC_INCLUDE' in environ: +if not environ.get('KIVY_DOC_INCLUDE'): # # Read, analyse configuration file From 31e494fc4856e8e5487f10e7999633f5f6db4c6a Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Mon, 23 Jul 2012 23:13:19 -0500 Subject: [PATCH 48/86] - fixed formatting of input factory --- kivy/input/factory.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kivy/input/factory.py b/kivy/input/factory.py index e8e50e5bc..94a092ff8 100644 --- a/kivy/input/factory.py +++ b/kivy/input/factory.py @@ -10,8 +10,8 @@ __all__ = ('MotionEventFactory', ) class MotionEventFactory: '''MotionEvent factory is a class who register all availables input - factories. If you create a new input factory, don't forget to register it - :: + factories. If you create a new input factory, don't forget to register + it:: MotionEventFactory.register('myproviderid', MyInputProvider) From c7408e0b0dce6116668db9c42b90677b709d0728 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Tue, 24 Jul 2012 00:52:34 -0500 Subject: [PATCH 49/86] - `make clean` removes *.so files - added exclude_patterns to sphinx config - changed doc reference to module reference in inputs.rst - reformated FloatLayout's documentation a bit - replaced references of RelativeFloatLayout with RelativeLayout --- Makefile | 1 + doc/sources/conf.py | 9 +++------ doc/sources/guide/inputs.rst | 2 +- kivy/graphics/transformation.pyx | 1 - kivy/uix/floatlayout.py | 21 ++++++++++----------- kivy/uix/relativelayout.py | 12 ++++++------ kivy/uix/tabbedpanel.py | 4 ++-- kivy/uix/textinput.py | 2 +- kivy/uix/treeview.py | 3 ++- 9 files changed, 26 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index 4e2cc7c75..8728eaa1c 100644 --- a/Makefile +++ b/Makefile @@ -48,6 +48,7 @@ clean: -rm .coverage -rm .noseids -rm -rf kivy/tests/build + -find kivy -iname '*.so' -exec rm {} \; -find kivy -iname '*.pyc' -exec rm {} \; -find kivy -iname '*.pyo' -exec rm {} \; diff --git a/doc/sources/conf.py b/doc/sources/conf.py index b060b1da8..43a051872 100644 --- a/doc/sources/conf.py +++ b/doc/sources/conf.py @@ -62,12 +62,9 @@ release = kivy.__version__ # Else, today_fmt is used as the format for a strftime call. today_fmt = '%B %d, %Y' -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# List of directories, relative to source directories, that shouldn't be searched -# for source files. -#exclude_dirs = [] +# suppress exclusion warnings +exclude_patterns = ['gettingstarted/*', 'api-index.rst', + 'api-kivy.lib.osc.*', 'guide/android.rst', 'guide/layouts.rst'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None diff --git a/doc/sources/guide/inputs.rst b/doc/sources/guide/inputs.rst index 2f4cea1aa..d36b238ca 100644 --- a/doc/sources/guide/inputs.rst +++ b/doc/sources/guide/inputs.rst @@ -96,7 +96,7 @@ profile exists:: if 'angle' in touch.profile: print 'The touch angle is', touch.a -You can find a list of available profiles in the :doc:`api-kivy.input.motionevent` +You can find a list of available profiles in the :mod:`api-kivy.input.motionevent` documentation. Touch events diff --git a/kivy/graphics/transformation.pyx b/kivy/graphics/transformation.pyx index 230833b37..5a22aa090 100644 --- a/kivy/graphics/transformation.pyx +++ b/kivy/graphics/transformation.pyx @@ -44,7 +44,6 @@ cdef class Matrix: [ 4 5 6 7] [ 8 9 10 11] [ 12 13 14 15] - ''' def __cinit__(self): diff --git a/kivy/uix/floatlayout.py b/kivy/uix/floatlayout.py index 61a5f1a55..3c10e2d07 100644 --- a/kivy/uix/floatlayout.py +++ b/kivy/uix/floatlayout.py @@ -15,28 +15,27 @@ The :class:`FloatLayout` class will only honor the :data:`Widget.pos_hint` and .. image:: images/floatlayout.png :align: right -For example, if you create a FloatLayout with size of (300, 300):: +For example, if you create a FloatLayout with size a of (300, 300):: layout = FloatLayout(size=(300, 300)) - # By default, all widgets have size_hint=(1, 1) - # So this button will have the same size as - # the layout +By default, all widgets have size_hint=(1, 1), so this button will have the +same size as the layout:: + button = Button(text='Hello world') layout.add_widget(button) - # To create a button of 50% width and 25% - # height of the layout and positioned at - # 20, 20, you can do +To create a button of 50% width and 25% height of the layout and positioned at +(20, 20), you can do:: + button = Button( text='Hello world', size_hint=(.5, .25), pos=(20, 20)) -:: +If you want to create a button that will always be the size of layout minus +20% on each side:: - # If you want to create a button that will always be the size of layout - # minus 20% on each side: button = Button(text='Hello world', size_hint=(.6, .6), pos_hint={'x':.2, 'y':.2}) @@ -53,7 +52,7 @@ For example, if you create a FloatLayout with size of (300, 300):: ''' -__all__ = ('FloatLayout', 'RelativeFloatLayout') +__all__ = ('FloatLayout',) from kivy.uix.layout import Layout diff --git a/kivy/uix/relativelayout.py b/kivy/uix/relativelayout.py index 79f08a357..f929ffc6f 100644 --- a/kivy/uix/relativelayout.py +++ b/kivy/uix/relativelayout.py @@ -7,24 +7,24 @@ Relative Layout This layout allows you to set relative coordinate for children. If you want absolute positioning, check :class:`~kivy.uix.floatlayout.FloatLayout`. -The :class:`RelativeFloatLayout` class behaves just like the regular Float +The :class:`RelativeLayout` class behaves just like the regular Float Layout, except that its child widgets are positioned relative to the layout. -For example, if you create a RelativeFloatLayout, add a widgets with +For example, if you create a RelativeLayout, add a widgets with position = (0,0), the child widget will also move, when you change the -position of the RelativeFloatLayout. The child widgets coordiantes remain +position of the RelativeLayout. The child widgets coordiantes remain (0,0), i.e. they are relative to the containing layout. ..note:: - The :class:`RelativeFloatLayout` is implemented as a :class`FloatLayout` + The :class:`RelativeLayout` is implemented as a :class`FloatLayout` inside a :class:`Scatter`. .. warning:: - Since the actual RelativeFloatLayout is a Scatter, its add_widget and + Since the actual RelativeLayout is a Scatter, its add_widget and remove_widget functions are overwritten to add children to the embedded - FloatLayout (accessible as `content` property of RelativeFloatLayout) + FloatLayout (accessible as `content` property of RelativeLayout) automatically. So if you want to access the added child elements, you need self.content.children, instead of self.children. ''' diff --git a/kivy/uix/tabbedpanel.py b/kivy/uix/tabbedpanel.py index fd2caac56..802ae2b85 100644 --- a/kivy/uix/tabbedpanel.py +++ b/kivy/uix/tabbedpanel.py @@ -252,7 +252,7 @@ class TabbedPanel(GridLayout): '''Specifies the text displayed on the default tab header. :data:`default_tab_text` is a :class:`~kivy.properties.StringProperty`, - default to 'default tab'. + defaults to 'default tab'. ''' default_tab_cls = ObjectProperty(TabbedPanelHeader) @@ -307,7 +307,7 @@ class TabbedPanel(GridLayout): '''Holds the default tab. .. Note:: For convenience, the automatically provided default tab is deleted - when you change default_tab to something else. + when you change default_tab to something else. :data:`default_tab` is a :class:`~kivy.properties.AliasProperty` ''' diff --git a/kivy/uix/textinput.py b/kivy/uix/textinput.py index a47585d95..2951518de 100644 --- a/kivy/uix/textinput.py +++ b/kivy/uix/textinput.py @@ -1209,7 +1209,7 @@ class TextInput(Widget): ''' password = BooleanProperty(False) - '''If True, the widget will display its characters as the character *. + '''If True, the widget will display its characters as the character '*'. .. versionadded:: 1.2.0 diff --git a/kivy/uix/treeview.py b/kivy/uix/treeview.py index 1cfc7fecb..4e365e0bf 100644 --- a/kivy/uix/treeview.py +++ b/kivy/uix/treeview.py @@ -355,7 +355,8 @@ class TreeView(Widget): def iterate_open_nodes(self, node=None): '''Generator to iterate over expanded nodes. - To get all the open nodes: + + To get all the open nodes:: treeview = TreeView() # ... add nodes ... From a292a297038b24d31ad9bb5e3d90188822c3e30a Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Wed, 25 Jul 2012 14:54:20 -0500 Subject: [PATCH 50/86] - updated import statements --- kivy/base.py | 3 ++- kivy/core/audio/audio_pygame.py | 4 ++-- kivy/core/camera/camera_opencv.py | 6 +++--- kivy/core/gl/__init__.py | 3 ++- kivy/core/image/__init__.py | 4 ++-- kivy/core/window/__init__.py | 3 ++- kivy/factory.py | 2 +- kivy/input/__init__.py | 3 ++- kivy/input/providers/__init__.py | 21 +++++++++++---------- kivy/input/providers/androidjoystick.py | 3 ++- kivy/lib/debug.py | 2 +- kivy/lib/osc/oscAPI.py | 3 ++- kivy/utils.py | 3 ++- 13 files changed, 34 insertions(+), 26 deletions(-) diff --git a/kivy/base.py b/kivy/base.py index 9e0cd746f..d58e69b3c 100644 --- a/kivy/base.py +++ b/kivy/base.py @@ -1,3 +1,4 @@ +# pylint: disable=W0611 ''' Event loop management ===================== @@ -105,7 +106,7 @@ class EventLoopBase(EventDispatcher): def ensure_window(self): '''Ensure that we have an window ''' - __import__('kivy.core.window') + import kivy.core.window def set_window(self, window): '''Set the window used for event loop diff --git a/kivy/core/audio/audio_pygame.py b/kivy/core/audio/audio_pygame.py index 633e963c9..7d064ad6d 100644 --- a/kivy/core/audio/audio_pygame.py +++ b/kivy/core/audio/audio_pygame.py @@ -10,9 +10,9 @@ from kivy.core.audio import Sound, SoundLoader try: if platform() == 'android': - mixer = __import__('android_mixer') + import android_mixer as mixer else: - mixer = __import__('pygame.mixer', fromlist='.') + from pygame import mixer except: raise diff --git a/kivy/core/camera/camera_opencv.py b/kivy/core/camera/camera_opencv.py index 2d6fcba7b..8eed6634d 100644 --- a/kivy/core/camera/camera_opencv.py +++ b/kivy/core/camera/camera_opencv.py @@ -14,10 +14,10 @@ from kivy.graphics.texture import Texture from kivy.core.camera import CameraBase try: - cv = __import__('opencv', fromlist='.') - hg = __import__('opencv.highgui', fromlist='.') + import opencv as cv + import opencv.highgui as hg except ImportError: - cv = __import__('cv') + import cv class Hg(object): ''' diff --git a/kivy/core/gl/__init__.py b/kivy/core/gl/__init__.py index f90389ea0..502b88c31 100644 --- a/kivy/core/gl/__init__.py +++ b/kivy/core/gl/__init__.py @@ -1,3 +1,4 @@ +# pylint: disable=W0611 ''' OpenGL ====== @@ -49,4 +50,4 @@ if 'KIVY_DOC' not in environ: # To be able to use our GL provider, we must have a window # Automaticly import window auto to ensure the default window creation - __import__('kivy.core.window') + import kivy.core.window diff --git a/kivy/core/image/__init__.py b/kivy/core/image/__init__.py index 61e97b852..994407b8a 100644 --- a/kivy/core/image/__init__.py +++ b/kivy/core/image/__init__.py @@ -22,9 +22,9 @@ from kivy.atlas import Atlas from kivy.resources import resource_find import zipfile try: - SIO = __import__('cStringIO') + import cStringIO as SIO except ImportError: - SIO = __import__('StringIO') + import StringIO as SIO # late binding diff --git a/kivy/core/window/__init__.py b/kivy/core/window/__init__.py index 1e300e85f..c29c051bc 100755 --- a/kivy/core/window/__init__.py +++ b/kivy/core/window/__init__.py @@ -1,3 +1,4 @@ +# pylint: disable=W0611 ''' Window ====== @@ -466,7 +467,7 @@ class WindowBase(EventDispatcher): self.parent = self # before creating the window - __import__('kivy.core.gl') + import kivy.core.gl # configure the window self.create_window() diff --git a/kivy/factory.py b/kivy/factory.py index a99f3c956..3f1e51002 100644 --- a/kivy/factory.py +++ b/kivy/factory.py @@ -90,7 +90,7 @@ Factory = FactoryBase() # Now import the file with all registers # automatically generated by build_factory -__import__('kivy.factory_registers') +import kivy.factory.registers Logger.info('Factory: %d symbols loaded' % len(Factory.classes)) if __name__ == '__main__': diff --git a/kivy/input/__init__.py b/kivy/input/__init__.py index 5aa8fa6a6..9c68f9fce 100644 --- a/kivy/input/__init__.py +++ b/kivy/input/__init__.py @@ -1,3 +1,4 @@ +# pylint: disable=W0611 ''' Input management ================ @@ -29,7 +30,7 @@ from kivy.input.motionevent import MotionEvent from kivy.input.postproc import kivy_postproc_modules from kivy.input.provider import MotionEventProvider from kivy.input.factory import MotionEventFactory -__import__('kivy.input.providers') +import kivy.input.providers __all__ = ( MotionEvent.__name__, diff --git a/kivy/input/providers/__init__.py b/kivy/input/providers/__init__.py index 70064f46e..d926e131f 100644 --- a/kivy/input/providers/__init__.py +++ b/kivy/input/providers/__init__.py @@ -1,3 +1,4 @@ +# pylint: disable=W0611 ''' Providers ========= @@ -9,51 +10,51 @@ import os from kivy.utils import platform as core_platform from kivy.logger import Logger -__import__('kivy.input.providers.tuio') -__import__('kivy.input.providers.mouse') +import kivy.input.providers.tuio +import kivy.input.providers.mouse platform = core_platform() if platform == 'win' or 'KIVY_DOC' in os.environ: try: - __import__('kivy.input.providers.wm_touch') - __import__('kivy.input.providers.wm_pen') + import 'kivy.input.providers.wm_touch' + import 'kivy.input.providers.wm_pen' except: err = 'Input: WM_Touch/WM_Pen not supported by your version of Windows' Logger.warning(err) if platform == 'macosx' or 'KIVY_DOC' in os.environ: try: - __import__('kivy.input.providers.mactouch') + import kivy.input.providers.mactouch except: err = 'Input: MacMultitouchSupport is not supported by your system' Logger.exception(err) if platform == 'linux' or 'KIVY_DOC' in os.environ: try: - __import__('kivy.input.providers.probesysfs') + import kivy.input.providers.probesysfs except: err = 'Input: ProbeSysfs is not supported by your version of linux' Logger.exception(err) try: - __import__('kivy.input.providers.mtdev') + import kivy.input.providers.mtdev except: err = 'Input: MTDev is not supported by your version of linux' Logger.exception(err) try: - __import__('kivy.input.providers.hidinput') + import 'kivy.input.providers.hidinput' except: err = 'Input: HIDInput is not supported by your version of linux' Logger.exception(err) if platform == 'android' or 'KIVY_DOC' in os.environ: try: - __import__('kivy.input.providers.linuxwacom') + import 'kivy.input.providers.linuxwacom' except: err = 'Input: LinuxWacom is not supported by your version of linux' Logger.exception(err) try: - __import__('kivy.input.providers.androidjoystick') + import 'kivy.input.providers.androidjoystick' except: err = 'Input: AndroidJoystick is not supported by your version of linux' Logger.exception(err) diff --git a/kivy/input/providers/androidjoystick.py b/kivy/input/providers/androidjoystick.py index f279ce29a..74a073bfa 100644 --- a/kivy/input/providers/androidjoystick.py +++ b/kivy/input/providers/androidjoystick.py @@ -1,9 +1,10 @@ +# pylint: disable=W0611 __all__ = ('AndroidMotionEventProvider', ) import os try: - __import__('android') + import android except ImportError: if 'KIVY_DOC' not in os.environ: raise Exception('android lib not found.') diff --git a/kivy/lib/debug.py b/kivy/lib/debug.py index 75cf1b59a..f88943912 100644 --- a/kivy/lib/debug.py +++ b/kivy/lib/debug.py @@ -21,7 +21,7 @@ from types import TracebackType, CodeType # on pypy we can take advantage of transparent proxies try: - tproxy = __import__('__pypy__') + import __pypy__ as tproxy except ImportError: tproxy = None diff --git a/kivy/lib/osc/oscAPI.py b/kivy/lib/osc/oscAPI.py index edaf455eb..6a7af537c 100644 --- a/kivy/lib/osc/oscAPI.py +++ b/kivy/lib/osc/oscAPI.py @@ -1,3 +1,4 @@ +# pylint: disable=W0611 ''' simpleOSC 0.2 ixi software - July, 2006 www.ixi-software.net @@ -38,7 +39,7 @@ try: raise use_multiprocessing = True from multiprocessing import Process, Queue, Value - __import__('multiprocessing.synchronize') + import multiprocessing.synchronize Logger.info('OSC: using for socket') except: use_multiprocessing = False diff --git a/kivy/utils.py b/kivy/utils.py index ed97f5cdd..43729ebed 100644 --- a/kivy/utils.py +++ b/kivy/utils.py @@ -1,3 +1,4 @@ +# pylint: disable=W0611 ''' Utils ===== @@ -332,7 +333,7 @@ def platform(): if _platform_android is None: try: - __import__('android') + import android _platform_android = True except ImportError: _platform_android = False From a96d6d13228c279d63e1f1321b247b32dbbe4e9f Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Wed, 25 Jul 2012 14:57:43 -0500 Subject: [PATCH 51/86] - fixed typo --- kivy/factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kivy/factory.py b/kivy/factory.py index 3f1e51002..c7ef953ec 100644 --- a/kivy/factory.py +++ b/kivy/factory.py @@ -90,7 +90,7 @@ Factory = FactoryBase() # Now import the file with all registers # automatically generated by build_factory -import kivy.factory.registers +import kivy.factory_registers Logger.info('Factory: %d symbols loaded' % len(Factory.classes)) if __name__ == '__main__': From fa921c3fa7dab317370ec2ad61a3384652932b68 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Fri, 27 Jul 2012 10:53:21 +0200 Subject: [PATCH 52/86] fix latest import pull request --- kivy/input/providers/__init__.py | 18 +++++++++--------- kivy/uix/anchorlayout.py | 1 + 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/kivy/input/providers/__init__.py b/kivy/input/providers/__init__.py index d926e131f..acb14947b 100644 --- a/kivy/input/providers/__init__.py +++ b/kivy/input/providers/__init__.py @@ -17,8 +17,8 @@ platform = core_platform() if platform == 'win' or 'KIVY_DOC' in os.environ: try: - import 'kivy.input.providers.wm_touch' - import 'kivy.input.providers.wm_pen' + import kivy.input.providers.wm_touch + import kivy.input.providers.wm_pen except: err = 'Input: WM_Touch/WM_Pen not supported by your version of Windows' Logger.warning(err) @@ -42,19 +42,19 @@ if platform == 'linux' or 'KIVY_DOC' in os.environ: err = 'Input: MTDev is not supported by your version of linux' Logger.exception(err) try: - import 'kivy.input.providers.hidinput' + import kivy.input.providers.hidinput except: err = 'Input: HIDInput is not supported by your version of linux' Logger.exception(err) + try: + import kivy.input.providers.linuxwacom + except: + err = 'Input: LinuxWacom is not supported by your version of linux' + Logger.exception(err) if platform == 'android' or 'KIVY_DOC' in os.environ: try: - import 'kivy.input.providers.linuxwacom' - except: - err = 'Input: LinuxWacom is not supported by your version of linux' - Logger.exception(err) - try: - import 'kivy.input.providers.androidjoystick' + import kivy.input.providers.androidjoystick except: err = 'Input: AndroidJoystick is not supported by your version of linux' Logger.exception(err) diff --git a/kivy/uix/anchorlayout.py b/kivy/uix/anchorlayout.py index e4c81ed4c..07d4b8083 100644 --- a/kivy/uix/anchorlayout.py +++ b/kivy/uix/anchorlayout.py @@ -61,6 +61,7 @@ class AnchorLayout(Layout): def __init__(self, **kwargs): super(AnchorLayout, self).__init__(**kwargs) self.bind( + children = self._trigger_layout, parent = self._trigger_layout, padding = self._trigger_layout, anchor_x = self._trigger_layout, From ba58922163ff7d802a6e83bb15b8e1123d75d427 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Fri, 27 Jul 2012 12:35:22 +0200 Subject: [PATCH 53/86] screenmanager: ensure the screen position is fixed to the screenmanager position. --- kivy/uix/screenmanager.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/kivy/uix/screenmanager.py b/kivy/uix/screenmanager.py index 1d5ecf39b..9c4ffa8b3 100644 --- a/kivy/uix/screenmanager.py +++ b/kivy/uix/screenmanager.py @@ -118,7 +118,7 @@ __all__ = ('Screen', 'ScreenManager', 'ScreenManagerException', from kivy.event import EventDispatcher from kivy.uix.floatlayout import FloatLayout from kivy.properties import StringProperty, ObjectProperty, \ - NumericProperty, ListProperty, OptionProperty + NumericProperty, ListProperty, OptionProperty, BooleanProperty from kivy.animation import Animation, AnimationTransition from kivy.uix.relativelayout import RelativeLayout from kivy.lang import Builder @@ -222,6 +222,13 @@ class TransitionBase(EventDispatcher): None, read-only. ''' + is_active = BooleanProperty() + '''Indicate if the transition is currently active + + :data:`is_active` is a :class:`~kivy.properties.BooleanProperty`, default to + False, read-only. + ''' + # privates _anim = ObjectProperty(allownone=True) @@ -246,6 +253,7 @@ class TransitionBase(EventDispatcher): self.screen_out.transition_progress = 0. self.screen_out.transition_mode = 'out' + self.is_active = True self._anim.start(self) self.dispatch('on_progress', 0) @@ -257,6 +265,7 @@ class TransitionBase(EventDispatcher): self._anim.cancel(self) self.dispatch('on_complete') self._anim = None + self.is_active = False def add_screen(self, screen): '''(internal) Used to add a screen into the :class:`ScreenManager` @@ -281,6 +290,7 @@ class TransitionBase(EventDispatcher): self.dispatch('on_progress', progress) def _on_complete(self, *l): + self.is_active = False self.dispatch('on_complete') self._anim = None @@ -550,6 +560,10 @@ class ScreenManager(FloatLayout): default to None, read-only. ''' + def __init__(self, **kwargs): + super(ScreenManager, self).__init__(**kwargs) + self.bind(pos=self._update_pos) + def add_widget(self, screen): if not isinstance(screen, Screen): raise ScreenManagerException( @@ -584,6 +598,7 @@ class ScreenManager(FloatLayout): self.transition.screen_out = previous_screen self.transition.start(self) else: + screen.pos = self.pos self.real_add_widget(screen) def get_screen(self, name): @@ -620,6 +635,14 @@ class ScreenManager(FloatLayout): except ValueError: return + def _update_pos(self, instance, value): + for child in self.children: + if self.transition.is_active and \ + (child == self.transition.screen_in or \ + child == self.transition.screen_out): + continue + child.pos = value + if __name__ == '__main__': from kivy.app import App from kivy.uix.button import Button From 915a94af24e65b0f1a8486fe38223d7719b3a973 Mon Sep 17 00:00:00 2001 From: Qua-non Date: Sat, 28 Jul 2012 04:44:40 +0530 Subject: [PATCH 54/86] UIX:TextInput: refactor undo_redo and selection_from/to Selection_from/to are now readonly and two new methods `select_all()` and `select_text(start, end)` have been provided for selection. --- kivy/uix/textinput.py | 141 +++++++++++++++++++++++++++--------------- 1 file changed, 92 insertions(+), 49 deletions(-) diff --git a/kivy/uix/textinput.py b/kivy/uix/textinput.py index 4ecc6d672..4a978b62e 100644 --- a/kivy/uix/textinput.py +++ b/kivy/uix/textinput.py @@ -161,8 +161,8 @@ class TextInput(Widget): self._selection_finished = True self._selection_touch = None self.selection_text = '' - self.selection_from = None - self.selection_to = None + self.__selection_from = None + self._selection_to = None self._bubble = None self._lines_flags = [] self._lines_labels = [] @@ -259,6 +259,24 @@ class TextInput(Widget): i = ni return index, row + def select_text(self, start, end): + ''' Select portion of text displayed in this TextInput + + .. version added:: 1.4.0 + + ''' + self._selection_from = start + self._selection_to = end + self._update_selection(True) + + def select_all(self): + ''' Select all of the text displayed in this TextInput + + .. version added:: 1.4.0 + + ''' + self.select_text(0, len(self.text)) + def insert_text(self, substring, from_undo = False): '''Insert new text on the current cursor position. ''' @@ -291,14 +309,8 @@ class TextInput(Widget): elif count > 0: cursor = cursor[0], cursor[1] + count - self._undo.append({'undo_command': \ - 'self.cursor = (%i, %i)\n' %(cursor[0], cursor[1]) +\ - 'self.selection_from = %i\nself.selection_to = %i\n' %(ci, sci())+ - 'self._selection = True\n'+\ - 'self.delete_selection(True)\n',\ - 'redo_command': \ - 'self.cursor = (%i, %i)\nself.insert_text(u\'%s\', True)'\ - %(cc, cr, substring.replace('\n', '\\n').replace('\'', '\\\''))}) + self._undo.append({'undo_command': ('insert', cursor, ci, sci()), + 'redo_command': (cc, cr, substring)}) #reset redo when undo is appended to self._redo = [] @@ -320,7 +332,25 @@ class TextInput(Widget): ''' try: x_item = self._redo.pop() - exec(x_item['redo_command']) + undo_type = x_item['undo_command'][0] + + if undo_type == 'insert': + cc, cr, substring = x_item['redo_command'] + self.cursor = cc, cr + self.insert_text(substring, True) + #substring.replace('\n', '\\n').replace('\'', '\\\'') + elif undo_type == 'bkspc': + cc, cr = x_item['redo_command'] + self.cursor = cc, cr + self.do_backspace(True) + else: + # delsel + ci, sci, cc, cr = x_item['redo_command'] + self._selection_from = ci + self._selection_to = sci + self._selection = True + self.delete_selection(True) + self.cursor = (cc, cr) self._undo.append(x_item) except IndexError: # reached at top of undo list @@ -337,7 +367,22 @@ class TextInput(Widget): ''' try: x_item = self._undo.pop() - exec(x_item['undo_command']) + undo_type = x_item['undo_command'][0] + self.cursor = x_item['undo_command'][1] + + if undo_type == 'insert': + ci, sci = x_item['undo_command'][2:] + self._selection_from = ci + self._selection_to = sci + self._selection = True + self.delete_selection(True) + elif undo_type == 'bkspc': + substring = x_item['undo_command'][2:] + self.insert_text(substring, True) + else: + # delsel + substring = x_item['undo_command'][2:][0] + self.insert_text(substring, True) self._redo.append(x_item) except IndexError: # reached at top of undo list @@ -383,13 +428,9 @@ class TextInput(Widget): if from_undo: return - self._undo.append({'undo_command': \ - 'self.cursor = (%i, %i)\n' %(cursor[0], cursor[1]) +\ - 'self.insert_text(u\'%s\', True)'\ - %(substring.replace('\n', '\\n').replace('\'', '\\\'')), - 'redo_command': \ - 'self.cursor = (%i, %i)\n' %(cc, cr)+\ - 'self.do_backspace(True)'}) + self._undo.append({ + 'undo_command': ('bkspc', cursor, substring), + 'redo_command': (cc, cr)}) #reset redo when undo is appended to self._redo = [] @@ -478,7 +519,7 @@ class TextInput(Widget): if not self._selection: return v = self.text - a, b = self.selection_from, self.selection_to + a, b = self._selection_from, self._selection_to if a > b: a, b = b, a text = v[:a] + v[b:] @@ -496,15 +537,9 @@ class TextInput(Widget): if from_undo: return - self._undo.append({'undo_command': \ - 'self.cursor = (%i, %i)\n' %(cursor[0], cursor[1]) +\ - 'self.insert_text(u\'%s\', True)'\ - %(substring.replace('\n', '\\n').replace('\'', '\\\'')), - 'redo_command': \ - 'self.selection_from = %i\nself.selection_to = %i\n' %(ci, sci)+ - 'self._selection = True\n'+\ - 'self.delete_selection(True)\n'+\ - 'self.cursor = (%i, %i)\n' %(cc, cr)}) + self._undo.append({ + 'undo_command': ('delsel', cursor, substring), + 'redo_command': (ci, sci, cc, cr)}) #reset redo when undo is appended to self._redo = [] @@ -512,7 +547,7 @@ class TextInput(Widget): '''Update selection text and order of from/to if finished is True. Can be called multiple times until finished is True. ''' - a, b = self.selection_from, self.selection_to + a, b = self._selection_from, self._selection_to if a > b: a, b = b, a self._selection_finished = finished @@ -541,7 +576,7 @@ class TextInput(Widget): if not self._selection_touch: self.cancel_selection() self._selection_touch = touch - self.selection_from = self.selection_to = self.cursor_index() + self._selection_from = self._selection_to = self.cursor_index() self._update_selection() return True @@ -555,7 +590,7 @@ class TextInput(Widget): return False if self._selection_touch is touch: self.cursor = self.get_cursor_from_xy(touch.x, touch.y) - self.selection_to = self.cursor_index() + self._selection_to = self.cursor_index() self._update_selection() return True @@ -566,7 +601,7 @@ class TextInput(Widget): if not self.focus: return False if self._selection_touch is touch: - self.selection_to = self.cursor_index() + self._selection_to = self.cursor_index() self._update_selection(True) # show Bubble win = self._win @@ -576,7 +611,7 @@ class TextInput(Widget): Logger.warning('Textinput: ' 'Cannot show bubble, unable to get root window') return True - if self.selection_to != self.selection_from: + if self._selection_to != self._selection_from: self._show_cut_copy_paste(touch.pos, win) else: self._hide_cut_copy_paste(win) @@ -915,7 +950,7 @@ class TextInput(Widget): maxy = _top - _padding_y draw_selection = self._draw_selection scroll_y = self.scroll_y - a, b = self.selection_from, self.selection_to + a, b = self._selection_from, self._selection_to if a > b: a, b = b, a get_cursor_from_index = self.get_cursor_from_index @@ -933,7 +968,7 @@ class TextInput(Widget): def _draw_selection(self, pos, size, line_num): # Draw the current selection on the widget. - a, b = self.selection_from, self.selection_to + a, b = self._selection_from, self._selection_to if a > b: a, b = b, a get_cursor_from_index = self.get_cursor_from_index @@ -1097,13 +1132,13 @@ class TextInput(Widget): self.insert_text(displayed_str) elif internal_action in ('shift', 'shift_L', 'shift_R'): if not self._selection: - self.selection_from = self.selection_to = self.cursor_index() + self._selection_from = self._selection_to = self.cursor_index() self._selection = True self._selection_finished = False elif internal_action.startswith('cursor_'): self.do_cursor_movement(internal_action) if self._selection and not self._selection_finished: - self.selection_to = self.cursor_index() + self._selection_to = self.cursor_index() self._update_selection() else: self.cancel_selection() @@ -1152,9 +1187,7 @@ class TextInput(Widget): elif key == ord('v'): # paste selection self._paste() elif key == ord('a'): # select all - self.selection_from = 0 - self.selection_to = len(self.text) - self._update_selection(True) + self.select_all() elif key == ord('z'): # undo self.do_undo() elif key == ord('r'): # redo @@ -1390,20 +1423,30 @@ class TextInput(Widget): default to [0, 0, 0, 1] #Black ''' - selection_from = NumericProperty(None, allownone=True) + def get_sel_from(self): + return self._selection_from + + selection_from = AliasProperty(get_sel_from, None) '''If a selection is happening, or finished, this property will represent the cursor index where the selection started. - :data:`selection_from` is a :class:`~kivy.properties.NumericProperty`, - default to None + .. versionchanged:: 1.4.0 + + :data:`selection_from` is a :class:`~kivy.properties.AliasProperty`, + default to None, readonly. ''' - selection_to = NumericProperty(None, allownone=True) - '''If a selection is happening, or finished, this property will represent - the cursor index where the selection ended. + def get_sel_to(self): + return self._selection_to - :data:`selection_to` is a :class:`~kivy.properties.NumericProperty`, - default to None + selection_to = AliasProperty(get_sel_to, None) + '''If a selection is happening, or finished, this property will represent + the cursor index where the selection started. + + .. versionchanged:: 1.4.0 + + :data:`selection_to` is a :class:`~kivy.properties.AliasProperty`, + default to None, readonly. ''' selection_text = StringProperty('') From 890ddc81adfae50394182d5e945e98ebeb4fed51 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Sat, 28 Jul 2012 07:19:22 +0200 Subject: [PATCH 55/86] fix versionadded + add some tests for select_text() --- kivy/uix/textinput.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/kivy/uix/textinput.py b/kivy/uix/textinput.py index 4a978b62e..3d57aa791 100644 --- a/kivy/uix/textinput.py +++ b/kivy/uix/textinput.py @@ -262,18 +262,19 @@ class TextInput(Widget): def select_text(self, start, end): ''' Select portion of text displayed in this TextInput - .. version added:: 1.4.0 - + .. versionadded:: 1.4.0 ''' - self._selection_from = start - self._selection_to = end + if end < start: + raise Exception('end must be superior to start') + m = len(self.text) + self._selection_from = boundary(start, 0, m) + self._selection_to = boundary(end, 0, m) self._update_selection(True) def select_all(self): ''' Select all of the text displayed in this TextInput - .. version added:: 1.4.0 - + .. versionadded:: 1.4.0 ''' self.select_text(0, len(self.text)) @@ -1453,7 +1454,7 @@ class TextInput(Widget): '''Current content selection. :data:`selection_text` is a :class:`~kivy.properties.StringProperty`, - default to '' + default to '', readonly. ''' focus = BooleanProperty(False) From 45e90bf9b35b510b8281e7ec357fa3ed9957c217 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Sat, 28 Jul 2012 08:05:05 +0200 Subject: [PATCH 56/86] dont activate the warning as error on sphinx, we need the gettingstarted generated, even if its not referenced in the toc + optim to not rewrite rst file if the content didnt change, it prevent sphinx to reread the source. --- doc/Makefile | 3 ++- doc/autobuild.py | 7 ++++++- doc/sources/conf.py | 4 ++-- doc/sources/guide/packaging.rst | 1 + 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index b544e0670..943ac23f0 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -3,7 +3,8 @@ # You can set these variables from the command line. PYTHON = python -SPHINXOPTS = -W +#SPHINXOPTS = -W +SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = diff --git a/doc/autobuild.py b/doc/autobuild.py index 06dfa6cb8..a42c2eadb 100644 --- a/doc/autobuild.py +++ b/doc/autobuild.py @@ -61,8 +61,13 @@ examples_framework_dir = os.path.join(base_dir, '..', 'examples', 'framework') def writefile(filename, data): global dest_dir - print 'write', filename + # avoid to rewrite the file if the content didn't change f = os.path.join(dest_dir, filename) + print 'write', filename + if os.path.exists(f): + with open(f) as fd: + if fd.read() == data: + return h = open(f, 'w') h.write(data) h.close() diff --git a/doc/sources/conf.py b/doc/sources/conf.py index 43a051872..975060499 100644 --- a/doc/sources/conf.py +++ b/doc/sources/conf.py @@ -63,8 +63,8 @@ release = kivy.__version__ today_fmt = '%B %d, %Y' # suppress exclusion warnings -exclude_patterns = ['gettingstarted/*', 'api-index.rst', - 'api-kivy.lib.osc.*', 'guide/android.rst', 'guide/layouts.rst'] +#exclude_patterns = ['gettingstarted/*', 'api-index.rst', +# 'api-kivy.lib.osc.*', 'guide/layouts.rst'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None diff --git a/doc/sources/guide/packaging.rst b/doc/sources/guide/packaging.rst index c7e6f6ffe..e8bdaa8e9 100644 --- a/doc/sources/guide/packaging.rst +++ b/doc/sources/guide/packaging.rst @@ -11,3 +11,4 @@ Packaging your application packaging-android packaging-ios + android From 4ae1b14d11d593a6307e4bb2ca52daaf2e03d599 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Sat, 28 Jul 2012 02:46:38 -0500 Subject: [PATCH 57/86] - trying a more flexible method of suppressing warnings - added reference to clock documentation --- doc/Makefile | 4 ++-- doc/sources/conf.py | 3 +-- doc/sources/contents.rst.inc | 1 + doc/sources/gettingstarted/framework.rst | 2 +- doc/sources/index.rst | 23 +++++++++++++++++++++++ kivy/clock.py | 4 ++++ 6 files changed, 32 insertions(+), 5 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index 943ac23f0..571a0b883 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -3,8 +3,8 @@ # You can set these variables from the command line. PYTHON = python -#SPHINXOPTS = -W -SPHINXOPTS = +SPHINXOPTS = -W +#SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = diff --git a/doc/sources/conf.py b/doc/sources/conf.py index 975060499..d4608cae1 100644 --- a/doc/sources/conf.py +++ b/doc/sources/conf.py @@ -63,8 +63,7 @@ release = kivy.__version__ today_fmt = '%B %d, %Y' # suppress exclusion warnings -#exclude_patterns = ['gettingstarted/*', 'api-index.rst', -# 'api-kivy.lib.osc.*', 'guide/layouts.rst'] +exclude_patterns = ['gettingstarted/*', 'guide/layouts.rst'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None diff --git a/doc/sources/contents.rst.inc b/doc/sources/contents.rst.inc index abe45c875..51533c074 100644 --- a/doc/sources/contents.rst.inc +++ b/doc/sources/contents.rst.inc @@ -6,6 +6,7 @@ and why you'd want to use it. It goes on with a discussion of the architecture and shows you how to create stunning applications in short time using the framework. + .. toctree:: :maxdepth: 2 diff --git a/doc/sources/gettingstarted/framework.rst b/doc/sources/gettingstarted/framework.rst index a42310cf9..c3d43c65b 100644 --- a/doc/sources/gettingstarted/framework.rst +++ b/doc/sources/gettingstarted/framework.rst @@ -15,7 +15,7 @@ Non-widget stuff .. |atlas_text| replace:: :class:`Atlas ` is a class for managing texture maps, i.e. packing multiple textures into one image. Using it allows you to reduce the number of images to load and speed up the application start. -.. |clock_text| replace:: :class:`Clock ` provides you with a convenient way to do jobs at set time intervals and is preferred over *sleep()* which would block the kivy Event Loop. These intervals can be set relative to the OpenGL Drawing instructions, :ref:`before ` or :ref:`after ` frame. Clock also provides you with a way to create :ref:`triggered events ` that are grouped together and only called once before the next frame. +.. |clock_text| replace:: :class:`Clock ` provides you with a convenient way to do jobs at set time intervals and is preferred over *sleep()* which would block the kivy Event Loop. These intervals can be set relative to the OpenGL Drawing instructions, :ref:`before ` or :ref:`after ` frame. Clock also provides you with a way to create :ref:`triggered events ` that are grouped together and only called once before the next frame. .. |sched_once| replace:: :meth:`~kivy.clock.ClockBase.schedule_once` .. |sched_intrvl| replace:: :meth:`~kivy.clock.ClockBase.schedule_interval` diff --git a/doc/sources/index.rst b/doc/sources/index.rst index fcbd1f03c..9c0c8bd6e 100644 --- a/doc/sources/index.rst +++ b/doc/sources/index.rst @@ -1,5 +1,6 @@ :orphan: + Welcome to Kivy =============== @@ -19,6 +20,28 @@ concern isn't addressed in the documentation, feel free to :ref:`contact`. .. include:: contents.rst.inc +.. Suppress warnings about documents not being included in toc, but don't + actually show them. +.. toctree:: + :hidden: + + api-index + api-kivy.lib.osc.OSC + api-kivy.lib.osc.oscAPI +.. gettingstarted/diving + gettingstarted/drawing + gettingstarted/events + gettingstarted/examples + gettingstarted/first_app + gettingstarted/framework + gettingstarted/installation + gettingstarted/intro + gettingstarted/layouts + gettingstarted/packaging + gettingstarted/properties + gettingstarted/rules + guide/layouts + Appendix ======== diff --git a/kivy/clock.py b/kivy/clock.py index 37a8a3988..b0fcd5e27 100644 --- a/kivy/clock.py +++ b/kivy/clock.py @@ -59,6 +59,8 @@ module:: # and keep the instance of foo, until you don't need it anymore! +.. _schedule-before-frame: + Schedule before frame --------------------- @@ -85,6 +87,8 @@ If you need to increase the limit, set the :data:`max_iteration` property:: from kivy.clock import Clock Clock.max_iteration = 20 +.. _triggered-events: + Triggered Events ---------------- From 325a0f31f943595aa4e86f64b2ab3787d034048a Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Sat, 28 Jul 2012 12:16:23 +0200 Subject: [PATCH 58/86] screenmanager: ensure the position is reset to the position of the screenmanager --- kivy/uix/screenmanager.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kivy/uix/screenmanager.py b/kivy/uix/screenmanager.py index 03f202b51..78352aabf 100644 --- a/kivy/uix/screenmanager.py +++ b/kivy/uix/screenmanager.py @@ -417,8 +417,8 @@ class SlideTransition(TransitionBase): a.y = y - height * (1 - progression) def on_complete(self): - self.screen_in.pos = (0, 0) - self.screen_out.pos = (0, 0) + self.screen_in.pos = self.manager.pos + self.screen_out.pos = self.manager.pos super(SlideTransition, self).on_complete() @@ -433,8 +433,8 @@ class SwapTransition(TransitionBase): def on_complete(self): self.screen_in.scale = 1. self.screen_out.scale = 1. - self.screen_in.pos = (0, 0) - self.screen_out.pos = (0, 0) + self.screen_in.pos = self.manager.pos + self.screen_out.pos = self.manager.pos super(SwapTransition, self).on_complete() def on_progress(self, progression): From 97843106b5366855b8aad348a6dfc90979f26440 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Sat, 28 Jul 2012 12:16:55 +0200 Subject: [PATCH 59/86] screenmanager: ensure the animation is not drawing outside the bounds of the screenmanager (todo: wipe transition doesn't seem to work.) --- kivy/data/style.kv | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/kivy/data/style.kv b/kivy/data/style.kv index 880f42841..53b8271b1 100644 --- a/kivy/data/style.kv +++ b/kivy/data/style.kv @@ -761,3 +761,23 @@ do_rotation: False do_scale: False auto_bring_to_front: False + + +# ============================================================================= +# Screen Manager +# ============================================================================= + +: + canvas.before: + StencilPush + Rectangle: + pos: self.pos + size: self.size + StencilUse + canvas.after: + StencilUnUse + Rectangle: + pos: self.pos + size: self.size + StencilPop + From a546c9828c295ab8618112516f1fd6dd89dc8556 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Sat, 28 Jul 2012 18:24:01 +0200 Subject: [PATCH 60/86] textinput: prevent the bubble to be showed if the textinput is not on the screen anymore (Check is done twice per seconds). --- kivy/uix/textinput.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/kivy/uix/textinput.py b/kivy/uix/textinput.py index 6b06e6b7e..df19cb6e7 100644 --- a/kivy/uix/textinput.py +++ b/kivy/uix/textinput.py @@ -133,6 +133,24 @@ class TextInputCutCopyPaste(Bubble): textinput = ObjectProperty(None) + def __init__(self, **kwargs): + super(TextInputCutCopyPaste, self).__init__(**kwargs) + Clock.schedule_interval(self._check_parent, .5) + + def _check_parent(self, dt): + # this is a prevention to get the Bubble staying on the screen, if the + # attached textinput is not on the screen anymore. + parent = self.textinput + while parent is not None: + if parent == parent.parent: + break + parent = parent.parent + if parent is None: + Clock.unschedule(self._check_parent) + if self.textinput: + self.textinput._hide_cut_copy_paste() + + def do(self, action): textinput = self.textinput @@ -618,7 +636,10 @@ class TextInput(Widget): self._hide_cut_copy_paste(win) return True - def _hide_cut_copy_paste(self, win): + def _hide_cut_copy_paste(self, win=None): + win = win or self._win + if win is None: + return bubble = self._bubble if bubble is not None: win.remove_widget(bubble) From 075f6c37b78d05895da091bc41063b537c02f4d4 Mon Sep 17 00:00:00 2001 From: Mark Eichin Date: Sun, 29 Jul 2012 16:04:39 -0300 Subject: [PATCH 61/86] docstring typo "self" is not a class name --- kivy/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kivy/app.py b/kivy/app.py index 330463742..7c3512549 100644 --- a/kivy/app.py +++ b/kivy/app.py @@ -151,7 +151,7 @@ However, you might want to know when a config value has been changed by the user, in order to adapt or reload your UI. You can overload the :meth:`on_config_change` method:: - class TestApp(self): + class TestApp(App): # ... def on_config_change(self, config, section, key, value): if config is self.config: From 9c68e7966527246f487067da12e703a406d23654 Mon Sep 17 00:00:00 2001 From: "gabriel.pettier" Date: Sun, 29 Jul 2012 21:43:01 +0200 Subject: [PATCH 62/86] remove all obsolete __android__ uses in __name__ tests --- examples/animation/animate.py | 2 +- examples/audio/main.py | 2 +- examples/demo/pictures/main.py | 2 +- examples/demo/shadereditor/main.py | 2 +- examples/demo/showcase/main.py | 2 +- examples/demo/touchtracer/main.py | 2 +- examples/guide/designwithkv/main.py | 2 +- examples/guide/quickstart/main.py | 2 +- examples/shader/shadertree.py | 2 +- examples/tutorials/pong/main.py | 2 +- examples/tutorials/pong/steps/step1/main.py | 2 +- examples/tutorials/pong/steps/step2/main.py | 2 +- examples/tutorials/pong/steps/step3/main.py | 2 +- examples/tutorials/pong/steps/step4/main.py | 2 +- examples/tutorials/pong/steps/step5/main.py | 2 +- examples/widgets/asyncimage.py | 2 +- examples/widgets/bubble_test.py | 2 +- examples/widgets/image_mipmap.py | 2 +- examples/widgets/label_mipmap.py | 2 +- examples/widgets/sequenced_images/main.py | 2 +- examples/widgets/tabbed_panel_showcase.py | 2 +- examples/widgets/videoplayer.py | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) diff --git a/examples/animation/animate.py b/examples/animation/animate.py index e63b603d6..4ae89ae12 100644 --- a/examples/animation/animate.py +++ b/examples/animation/animate.py @@ -32,6 +32,6 @@ class TestApp(App): button.bind(on_press=self.animate) return button -if __name__ in ('__main__', '__android__'): +if __name__ == '__main__': TestApp().run() diff --git a/examples/audio/main.py b/examples/audio/main.py index fef40c42a..9afcdc919 100644 --- a/examples/audio/main.py +++ b/examples/audio/main.py @@ -57,5 +57,5 @@ class AudioApp(App): return root -if __name__ in ('__android__', '__main__'): +if __name__ == '__main__': AudioApp().run() diff --git a/examples/demo/pictures/main.py b/examples/demo/pictures/main.py index ea0062347..cf05b9423 100644 --- a/examples/demo/pictures/main.py +++ b/examples/demo/pictures/main.py @@ -53,6 +53,6 @@ class PicturesApp(App): return True -if __name__ in ('__main__', '__android__'): +if __name__ == '__main__': PicturesApp().run() diff --git a/examples/demo/shadereditor/main.py b/examples/demo/shadereditor/main.py index c061fdfd1..099134de5 100644 --- a/examples/demo/shadereditor/main.py +++ b/examples/demo/shadereditor/main.py @@ -108,5 +108,5 @@ class ShaderEditorApp(App): def build(self): return ShaderEditor() -if __name__ in ('__main__', '__android__'): +if __name__ == '__main__': ShaderEditorApp().run() diff --git a/examples/demo/showcase/main.py b/examples/demo/showcase/main.py index e31528a1b..7c1923beb 100644 --- a/examples/demo/showcase/main.py +++ b/examples/demo/showcase/main.py @@ -277,5 +277,5 @@ class ShowcaseApp(App): tv.add_node(TreeViewLabel(text='Subitem %d' % x), n) return tv -if __name__ in ('__main__', '__android__'): +if __name__ == '__main__': ShowcaseApp().run() diff --git a/examples/demo/touchtracer/main.py b/examples/demo/touchtracer/main.py index 0f68f76b4..76e601463 100644 --- a/examples/demo/touchtracer/main.py +++ b/examples/demo/touchtracer/main.py @@ -98,5 +98,5 @@ class TouchtracerApp(App): def on_pause(self): return True -if __name__ in ('__main__', '__android__'): +if __name__ == '__main__': TouchtracerApp().run() diff --git a/examples/guide/designwithkv/main.py b/examples/guide/designwithkv/main.py index 133b27837..08b220405 100644 --- a/examples/guide/designwithkv/main.py +++ b/examples/guide/designwithkv/main.py @@ -24,5 +24,5 @@ class ControllerApp(App): def build(self): return Controller(info='Hello world') -if __name__ in ('__android__', '__main__'): +if __name__ == '__main__': ControllerApp().run() diff --git a/examples/guide/quickstart/main.py b/examples/guide/quickstart/main.py index 4597bb275..481b8bccb 100644 --- a/examples/guide/quickstart/main.py +++ b/examples/guide/quickstart/main.py @@ -10,5 +10,5 @@ class MyApp(App): def build(self): return Button(text='Hello World') -if __name__ in ('__android__', '__main__'): +if __name__ == '__main__': MyApp().run() diff --git a/examples/shader/shadertree.py b/examples/shader/shadertree.py index c9d022d2c..eb379d417 100644 --- a/examples/shader/shadertree.py +++ b/examples/shader/shadertree.py @@ -201,5 +201,5 @@ class ShaderTreeApp(App): root.add_widget(btn) return root -if __name__ in ('__main__', '__android__'): +if __name__ == '__main__': ShaderTreeApp().run() diff --git a/examples/tutorials/pong/main.py b/examples/tutorials/pong/main.py index 349297312..677319376 100644 --- a/examples/tutorials/pong/main.py +++ b/examples/tutorials/pong/main.py @@ -80,5 +80,5 @@ class PongApp(App): -if __name__ in ('__android__', '__main__'): +if __name__ == '__main__': PongApp().run() diff --git a/examples/tutorials/pong/steps/step1/main.py b/examples/tutorials/pong/steps/step1/main.py index 60eb7def8..713280323 100644 --- a/examples/tutorials/pong/steps/step1/main.py +++ b/examples/tutorials/pong/steps/step1/main.py @@ -9,5 +9,5 @@ class PongApp(App): def build(self): return PongGame() -if __name__ in ('__android__', '__main__'): +if __name__ == '__main__': PongApp().run() diff --git a/examples/tutorials/pong/steps/step2/main.py b/examples/tutorials/pong/steps/step2/main.py index 60eb7def8..713280323 100644 --- a/examples/tutorials/pong/steps/step2/main.py +++ b/examples/tutorials/pong/steps/step2/main.py @@ -9,5 +9,5 @@ class PongApp(App): def build(self): return PongGame() -if __name__ in ('__android__', '__main__'): +if __name__ == '__main__': PongApp().run() diff --git a/examples/tutorials/pong/steps/step3/main.py b/examples/tutorials/pong/steps/step3/main.py index 283139464..e731e21e8 100644 --- a/examples/tutorials/pong/steps/step3/main.py +++ b/examples/tutorials/pong/steps/step3/main.py @@ -24,5 +24,5 @@ class PongApp(App): Factory.register("PongBall", PongBall) -if __name__ in ('__android__', '__main__'): +if __name__ == '__main__': PongApp().run() diff --git a/examples/tutorials/pong/steps/step4/main.py b/examples/tutorials/pong/steps/step4/main.py index 09c7d2b42..1f4182615 100644 --- a/examples/tutorials/pong/steps/step4/main.py +++ b/examples/tutorials/pong/steps/step4/main.py @@ -44,5 +44,5 @@ class PongApp(App): Factory.register("PongBall", PongBall) -if __name__ in ('__android__', '__main__'): +if __name__ == '__main__': PongApp().run() diff --git a/examples/tutorials/pong/steps/step5/main.py b/examples/tutorials/pong/steps/step5/main.py index 6d1a1fc79..bb4cafd53 100644 --- a/examples/tutorials/pong/steps/step5/main.py +++ b/examples/tutorials/pong/steps/step5/main.py @@ -79,5 +79,5 @@ class PongApp(App): -if __name__ in ('__android__', '__main__'): +if __name__ == '__main__': PongApp().run() diff --git a/examples/widgets/asyncimage.py b/examples/widgets/asyncimage.py index def28d690..24bf2d4a3 100644 --- a/examples/widgets/asyncimage.py +++ b/examples/widgets/asyncimage.py @@ -29,5 +29,5 @@ class TestAsyncApp(App): return CenteredAsyncImage( source='http://icanhascheezburger.files.wordpress.com/2009/12/funny-pictures-cat-is-expecting-you.jpg') -if __name__ in ('__main__', '__android__'): +if __name__ == '__main__': TestAsyncApp().run() diff --git a/examples/widgets/bubble_test.py b/examples/widgets/bubble_test.py index b25401f0d..83a53f87a 100644 --- a/examples/widgets/bubble_test.py +++ b/examples/widgets/bubble_test.py @@ -56,5 +56,5 @@ class TestBubbleApp(App): def build(self): return BubbleShowcase() -if __name__ in ('__main__', '__android__'): +if __name__ == '__main__': TestBubbleApp().run() diff --git a/examples/widgets/image_mipmap.py b/examples/widgets/image_mipmap.py index 32c625243..996167251 100644 --- a/examples/widgets/image_mipmap.py +++ b/examples/widgets/image_mipmap.py @@ -25,5 +25,5 @@ class LabelMipmapTest(App): s.add_widget(l2) return s -if __name__ in ('__main__', '__android__'): +if __name__ == '__main__': LabelMipmapTest().run() diff --git a/examples/widgets/label_mipmap.py b/examples/widgets/label_mipmap.py index 365cfb065..57590e94e 100644 --- a/examples/widgets/label_mipmap.py +++ b/examples/widgets/label_mipmap.py @@ -22,5 +22,5 @@ class LabelMipmapTest(App): s.add_widget(l2) return s -if __name__ in ('__main__', '__android__'): +if __name__ == '__main__': LabelMipmapTest().run() diff --git a/examples/widgets/sequenced_images/main.py b/examples/widgets/sequenced_images/main.py index 7db777b22..f2bc045d7 100644 --- a/examples/widgets/sequenced_images/main.py +++ b/examples/widgets/sequenced_images/main.py @@ -143,5 +143,5 @@ class mainApp(App): return upl -if __name__ in ('__main__', '__android__'): +if __name__ == '__main__': mainApp().run() diff --git a/examples/widgets/tabbed_panel_showcase.py b/examples/widgets/tabbed_panel_showcase.py index 343246e71..2bdff4ba9 100644 --- a/examples/widgets/tabbed_panel_showcase.py +++ b/examples/widgets/tabbed_panel_showcase.py @@ -330,5 +330,5 @@ class TestTabApp(App): def build(self): return TabShowcase() -if __name__ in ('__main__', '__android__'): +if __name__ == '__main__': TestTabApp().run() diff --git a/examples/widgets/videoplayer.py b/examples/widgets/videoplayer.py index 433b233c3..fa444213b 100644 --- a/examples/widgets/videoplayer.py +++ b/examples/widgets/videoplayer.py @@ -18,5 +18,5 @@ class VideoPlayerApp(App): return VideoPlayer(source=filename, play=True) -if __name__ in ('__main__', '__android__'): +if __name__ == '__main__': VideoPlayerApp().run() From 33c2906b741cb2c98ef2ce6c58ef2ec7e9a8b3d8 Mon Sep 17 00:00:00 2001 From: Mark Eichin Date: Sun, 29 Jul 2012 17:01:58 -0300 Subject: [PATCH 63/86] force blank dirname to '.' for safer substitution Issue #595, using %-substitution isn't as clever as os.path.join is. --- kivy/app.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kivy/app.py b/kivy/app.py index 7c3512549..ef387b91c 100644 --- a/kivy/app.py +++ b/kivy/app.py @@ -370,6 +370,8 @@ class App(EventDispatcher): ''' try: default_kv_directory = dirname(getfile(self.__class__)) + if default_kv_directory == '': + default_kv_directory = '.' except TypeError: # if it's a builtin module.. use the current dir. default_kv_directory = '.' @@ -491,6 +493,8 @@ class App(EventDispatcher): if self._app_directory is None: try: self._app_directory = dirname(getfile(self.__class__)) + if self._app_directory == '': + self._app_directory = '.' except TypeError: # if it's a builtin module.. use the current dir. self._app_directory = '.' From 357e9a2afaeea698cd91788b5273d2830b35e280 Mon Sep 17 00:00:00 2001 From: "gabriel.pettier" Date: Sun, 29 Jul 2012 22:17:02 +0200 Subject: [PATCH 64/86] stylefixes --- examples/animation/animate.py | 1 - kivy/logger.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/animation/animate.py b/examples/animation/animate.py index 4ae89ae12..0b642b036 100644 --- a/examples/animation/animate.py +++ b/examples/animation/animate.py @@ -34,4 +34,3 @@ class TestApp(App): if __name__ == '__main__': TestApp().run() - diff --git a/kivy/logger.py b/kivy/logger.py index 90ab9f8e2..b3a356851 100644 --- a/kivy/logger.py +++ b/kivy/logger.py @@ -288,7 +288,8 @@ if 'KIVY_NO_CONSOLELOG' not in os.environ: Logger.addHandler(getattr(sys, '_kivy_logging_handler')) else: use_color = os.name != 'nt' - color_fmt = formatter_message('[%(levelname)-18s] %(message)s', use_color) + color_fmt = formatter_message( + '[%(levelname)-18s] %(message)s', use_color) formatter = ColoredFormatter(color_fmt, use_color=use_color) console = ConsoleHandler() console.setFormatter(formatter) @@ -299,4 +300,3 @@ sys.stderr = LogFile('stderr', Logger.warning) #: Kivy history handler LoggerHistory = LoggerHistory - From 20b703e446628c6ed5a72473c9c788bb77488819 Mon Sep 17 00:00:00 2001 From: "gabriel.pettier" Date: Sun, 29 Jul 2012 22:28:40 +0200 Subject: [PATCH 65/86] style fixes --- kivy/input/providers/wm_touch.py | 2 +- kivy/tools/benchmark.py | 6 ++---- kivy/utils.py | 1 + 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/kivy/input/providers/wm_touch.py b/kivy/input/providers/wm_touch.py index 12f897fb2..259bab51e 100644 --- a/kivy/input/providers/wm_touch.py +++ b/kivy/input/providers/wm_touch.py @@ -119,7 +119,7 @@ else: windll.user32.GetTouchInputInfo.restype = BOOL windll.user32.GetTouchInputInfo.argtypes = [HANDLE, UINT, POINTER(TOUCHINPUT), c_int] - + class WM_MotionEventProvider(MotionEventProvider): def start(self): diff --git a/kivy/tools/benchmark.py b/kivy/tools/benchmark.py index 4c4b246bb..0057f7629 100644 --- a/kivy/tools/benchmark.py +++ b/kivy/tools/benchmark.py @@ -222,10 +222,8 @@ if reply.lower().strip() in ('', 'y'): payload = { 'public': True, 'files': { 'benchmark.txt': { - 'content': '\n'.join(report) - } - } - } + 'content': '\n'.join(report)}}} + r = requests.post('https://api.github.com/gists', data=json.dumps(payload)) diff --git a/kivy/utils.py b/kivy/utils.py index cf8f1933d..6a64b9bef 100644 --- a/kivy/utils.py +++ b/kivy/utils.py @@ -356,6 +356,7 @@ def platform(): return 'linux' return 'unknown' + def escape_markup(text): ''' Escape markup characters found in the text. Intended to be used when markup From be716e10f5e84d90ac89734d2c08f5cc11468563 Mon Sep 17 00:00:00 2001 From: "gabriel.pettier" Date: Sun, 29 Jul 2012 23:40:59 +0200 Subject: [PATCH 66/86] style fixes --- kivy/core/window/__init__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/kivy/core/window/__init__.py b/kivy/core/window/__init__.py index 87276bed6..833fc3021 100755 --- a/kivy/core/window/__init__.py +++ b/kivy/core/window/__init__.py @@ -764,7 +764,7 @@ class WindowBase(EventDispatcher): pass def on_keyboard(self, key, - scancode=None, codepoint=None, modifier=None ,**kwargs): + scancode=None, codepoint=None, modifier=None, **kwargs): '''Event called when keyboard is in action .. warning:: @@ -775,7 +775,6 @@ class WindowBase(EventDispatcher): "and will be removed in future versions. Use codepoint " "instead, which has identical semantics.") - def on_key_down(self, key, scancode=None, codepoint=None, modifier=None, **kwargs): '''Event called when a key is down (same arguments as on_keyboard)''' @@ -974,4 +973,3 @@ class WindowBase(EventDispatcher): Window = core_select_lib('window', ( ('pygame', 'window_pygame', 'WindowPygame'), ), True) - From ae89d97996c32811c14bac1b5709a8bdd1b33169 Mon Sep 17 00:00:00 2001 From: "gabriel.pettier" Date: Sun, 29 Jul 2012 23:42:42 +0200 Subject: [PATCH 67/86] style fixes --- kivy/tests/test_properties.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/kivy/tests/test_properties.py b/kivy/tests/test_properties.py index a0980fcfb..4db18bb75 100644 --- a/kivy/tests/test_properties.py +++ b/kivy/tests/test_properties.py @@ -78,7 +78,7 @@ class PropertiesTestCase(unittest.TestCase): self.assertEqual(a.get(wid), 'hello') try: - a.set(wid, 88) # number shouldn't be accepted + a.set(wid, 88) # number shouldn't be accepted self.fail('string accept number, fail.') except ValueError: pass @@ -94,7 +94,7 @@ class PropertiesTestCase(unittest.TestCase): self.assertEqual(a.get(wid), 99) try: - a.set(wid, '') # string shouldn't be accepted + a.set(wid, '') # string shouldn't be accepted self.fail('number accept string, fail.') except ValueError: pass @@ -119,7 +119,6 @@ class PropertiesTestCase(unittest.TestCase): a.set(wid, {'foo': 'bar'}) self.assertEqual(a.get(wid), {'foo': 'bar'}) - def test_propertynone(self): from kivy.properties import NumericProperty @@ -269,4 +268,3 @@ class PropertiesTestCase(unittest.TestCase): observe_called = 0 x.get(wid).update({'bleh': 5}) self.assertEqual(observe_called, 1) - From 74e9d0b11a2cddf622e68dc5dad43b99fb5a3ad3 Mon Sep 17 00:00:00 2001 From: "gabriel.pettier" Date: Mon, 30 Jul 2012 00:29:40 +0200 Subject: [PATCH 68/86] style fixes --- kivy/uix/textinput.py | 60 ++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/kivy/uix/textinput.py b/kivy/uix/textinput.py index df19cb6e7..541349cf4 100644 --- a/kivy/uix/textinput.py +++ b/kivy/uix/textinput.py @@ -150,7 +150,6 @@ class TextInputCutCopyPaste(Bubble): if self.textinput: self.textinput._hide_cut_copy_paste() - def do(self, action): textinput = self.textinput @@ -296,7 +295,7 @@ class TextInput(Widget): ''' self.select_text(0, len(self.text)) - def insert_text(self, substring, from_undo = False): + def insert_text(self, substring, from_undo=False): '''Insert new text on the current cursor position. ''' if self.readonly: @@ -407,7 +406,7 @@ class TextInput(Widget): # reached at top of undo list pass - def do_backspace(self, from_undo = False): + def do_backspace(self, from_undo=False): '''Do backspace operation from the current cursor position. This action might do several things: @@ -430,8 +429,8 @@ class TextInput(Widget): substring = '\n' else: #ch = text[cc-1] - substring = text[cc-1] - new_text = text[:cc-1] + text[cc:] + substring = text[cc - 1] + new_text = text[:cc - 1] + text[cc:] self._set_line_text(cr, new_text) # refresh_text seems to be unnecessary here @@ -503,11 +502,11 @@ class TextInput(Widget): dy = self.line_height + self._line_spacing cx = x - self.x scrl_y = self.scroll_y - scrl_y = scrl_y/ dy if scrl_y > 0 else 0 + scrl_y = scrl_y / dy if scrl_y > 0 else 0 cy = (self.top - self.padding_y + scrl_y * dy) - y cy = int(boundary(round(cy / dy), 0, len(l) - 1)) dcx = 0 - for i in xrange(1, len(l[cy])+1): + for i in xrange(1, len(l[cy]) + 1): if self._get_text_width(l[cy][:i]) >= cx: break dcx = i @@ -525,7 +524,7 @@ class TextInput(Widget): self._selection_touch = None self._trigger_update_graphics() - def delete_selection(self, from_undo = False): + def delete_selection(self, from_undo=False): '''Delete the current text selection (if any). ''' if self.readonly: @@ -533,8 +532,8 @@ class TextInput(Widget): scrl_x = self.scroll_x scrl_y = self.scroll_y cc, cr = self.cursor - sci = self.cursor_index - ci = sci() + #sci = self.cursor_index + #ci = sci() if not self._selection: return v = self.text @@ -644,7 +643,7 @@ class TextInput(Widget): if bubble is not None: win.remove_widget(bubble) - def _show_cut_copy_paste(self, pos, win, parent_changed = False, *l): + def _show_cut_copy_paste(self, pos, win, parent_changed=False, *l): # Show a bubble with cut copy and paste buttons bubble = self._bubble if bubble is None: @@ -670,7 +669,7 @@ class TextInput(Widget): # FIXME found a way to have that feature available for everybody if bubble_pos[0] < 0: # bubble beyond left of window - if bubble.pos[1] > (win_size[1]- bubble_size[1]): + if bubble.pos[1] > (win_size[1] - bubble_size[1]): # bubble above window height bubble.pos = (0, (t_pos[1]) - (bubble_size[1] + lh + ls)) bubble.arrow_pos = 'top_left' @@ -679,7 +678,7 @@ class TextInput(Widget): bubble.arrow_pos = 'bottom_left' elif bubble.right > win_size[0]: # bubble beyond right of window - if bubble_pos[1] > (win_size[1]- bubble_size[1]): + if bubble_pos[1] > (win_size[1] - bubble_size[1]): # bubble above window height bubble.pos = (win_size[0] - bubble_size[0], (t_pos[1]) - (bubble_size[1] + lh + ls)) @@ -688,7 +687,7 @@ class TextInput(Widget): bubble.right = win_size[0] bubble.arrow_pos = 'bottom_right' else: - if bubble_pos[1] > (win_size[1]- bubble_size[1]): + if bubble_pos[1] > (win_size[1] - bubble_size[1]): # bubble above window height bubble.pos = (bubble_pos[0], (t_pos[1]) - (bubble_size[1] + lh + ls)) @@ -743,6 +742,7 @@ class TextInput(Widget): return if Clipboard is None: from kivy.core.clipboard import Clipboard + Clipboard _platform = platform() if _platform == 'win': self._clip_mime_type = 'text/plain;charset=utf-8' @@ -945,7 +945,15 @@ class TextInput(Widget): tch = (vh / float(lh)) * oh size[1] = vh - texc = (tcx, tcy+tch, tcx+tcw, tcy+tch, tcx+tcw, tcy, tcx, tcy) + texc = ( + tcx, + tcy + tch, + tcx + tcw, + tcy + tch, + tcx + tcw, + tcy, + tcx, + tcy) # add rectangle. r = rects[line_num] @@ -971,7 +979,7 @@ class TextInput(Widget): miny = self.y + _padding_y maxy = _top - _padding_y draw_selection = self._draw_selection - scroll_y = self.scroll_y + #scroll_y = self.scroll_y a, b = self._selection_from, self._selection_to if a > b: a, b = b, a @@ -1099,8 +1107,8 @@ class TextInput(Widget): continue if oldindex != index: yield text[oldindex:index] - yield text[index:index+1] - oldindex = index+1 + yield text[index:index + 1] + oldindex = index + 1 yield text[oldindex:] def _split_smart(self, text): @@ -1202,17 +1210,17 @@ class TextInput(Widget): if text and not key in (self.interesting_keys.keys() + [27]): # This allows *either* ctrl *or* cmd, but not both. if modifiers == ['ctrl'] or (is_osx and modifiers == ['meta']): - if key == ord('x'): # cut selection + if key == ord('x'): # cut selection self._cut(self.selection_text) - elif key == ord('c'): # copy selection + elif key == ord('c'): # copy selection self._copy(self.selection_text) - elif key == ord('v'): # paste selection + elif key == ord('v'): # paste selection self._paste() - elif key == ord('a'): # select all + elif key == ord('a'): # select all self.select_all() - elif key == ord('z'): # undo + elif key == ord('z'): # undo self.do_undo() - elif key == ord('r'): # redo + elif key == ord('r'): # redo self.do_redo() else: if self._selection: @@ -1221,10 +1229,10 @@ class TextInput(Widget): #self._recalc_size() return - if key == 27: # escape + if key == 27: # escape self.focus = False return True - elif key == 9: # tab + elif key == 9: # tab self.insert_text('\t') return True From abb0e85b07e4f7304eafefb45a2ac4b8c76ecb32 Mon Sep 17 00:00:00 2001 From: "gabriel.pettier" Date: Mon, 30 Jul 2012 00:33:48 +0200 Subject: [PATCH 69/86] style fixes --- kivy/uix/accordion.py | 14 +++++++------- kivy/uix/floatlayout.py | 29 ++++++++++++++--------------- kivy/uix/label.py | 7 +++---- kivy/uix/layout.py | 2 +- kivy/uix/modalview.py | 19 ++++++++++--------- 5 files changed, 35 insertions(+), 36 deletions(-) diff --git a/kivy/uix/accordion.py b/kivy/uix/accordion.py index 9f9f03041..f8e37a93b 100644 --- a/kivy/uix/accordion.py +++ b/kivy/uix/accordion.py @@ -110,8 +110,8 @@ class AccordionItem(FloatLayout): title = StringProperty('') '''Title string of the item. The title might be used in conjuction with the - `AccordionItemTitle` template. If you are using a custom template, you can - use that property as a text entry, or not. By default, it's used for the + `AccordionItemTitle` template. If you are using a custom template, you can + use that property as a text entry, or not. By default, it's used for the title text. See title_template and the example below. :data:`title` is a :class:`~kivy.properties.StringProperty`, default to '' @@ -330,11 +330,11 @@ class Accordion(Widget): super(Accordion, self).__init__(**kwargs) self._trigger_layout = Clock.create_trigger(self._do_layout, -1) self.bind( - orientation = self._trigger_layout, - children = self._trigger_layout, - size = self._trigger_layout, - pos = self._trigger_layout, - min_space = self._trigger_layout) + orientation=self._trigger_layout, + children=self._trigger_layout, + size=self._trigger_layout, + pos=self._trigger_layout, + min_space=self._trigger_layout) def add_widget(self, widget, *largs): if not isinstance(widget, AccordionItem): diff --git a/kivy/uix/floatlayout.py b/kivy/uix/floatlayout.py index 3c10e2d07..3e449c428 100644 --- a/kivy/uix/floatlayout.py +++ b/kivy/uix/floatlayout.py @@ -52,7 +52,7 @@ If you want to create a button that will always be the size of layout minus ''' -__all__ = ('FloatLayout',) +__all__ = ('FloatLayout', ) from kivy.uix.layout import Layout @@ -65,11 +65,11 @@ class FloatLayout(Layout): kwargs.setdefault('size', (1, 1)) super(FloatLayout, self).__init__(**kwargs) self.bind( - children = self._trigger_layout, - pos = self._trigger_layout, - pos_hint = self._trigger_layout, - size_hint = self._trigger_layout, - size = self._trigger_layout) + children=self._trigger_layout, + pos=self._trigger_layout, + pos_hint=self._trigger_layout, + size_hint=self._trigger_layout, + size=self._trigger_layout) def do_layout(self, *largs): # optimization, until the size is 1, 1, don't do layout @@ -109,17 +109,16 @@ class FloatLayout(Layout): def add_widget(self, widget, index=0): widget.bind( - size = self._trigger_layout, - size_hint = self._trigger_layout, - pos = self._trigger_layout, - pos_hint = self._trigger_layout) + size=self._trigger_layout, + size_hint=self._trigger_layout, + pos=self._trigger_layout, + pos_hint=self._trigger_layout) return super(Layout, self).add_widget(widget, index) def remove_widget(self, widget): widget.unbind( - size = self._trigger_layout, - size_hint = self._trigger_layout, - pos = self._trigger_layout, - pos_hint = self._trigger_layout) + size=self._trigger_layout, + size_hint=self._trigger_layout, + pos=self._trigger_layout, + pos_hint=self._trigger_layout) return super(Layout, self).remove_widget(widget) - diff --git a/kivy/uix/label.py b/kivy/uix/label.py index 2e1603998..b73239333 100644 --- a/kivy/uix/label.py +++ b/kivy/uix/label.py @@ -78,7 +78,7 @@ to detect when the user clicks on part of the text, and to react. The tag ``[ref=xxx]`` is used for that. In this example, we are creating a reference on the word "World". When a click -happens on it, the function ``print_it`` will be called with the name of the +happens on it, the function ``print_it`` will be called with the name of the reference:: def print_it(instance, value): @@ -354,7 +354,7 @@ class Label(Widget): texture = ObjectProperty(None, allownone=True) '''Texture object of the text. The text is rendered automatically when a property changes. The OpenGL texture - created in this operation is stored in this property. You can use this + created in this operation is stored in this property. You can use this :data:`texture` for any graphics elements. Depending on the texture creation, the value will be a @@ -467,7 +467,7 @@ class Label(Widget): [anchor=content]Hello world """ - Then, all the ``[anchor=]`` references will be removed, and you'll get all + Then, all the ``[anchor=]`` references will be removed, and you'll get all the anchor positions in this property (only after rendering):: >>> widget = Label(text=text, markup=True) @@ -481,4 +481,3 @@ class Label(Widget): True. ''' - diff --git a/kivy/uix/layout.py b/kivy/uix/layout.py index 000497d19..ee8490753 100644 --- a/kivy/uix/layout.py +++ b/kivy/uix/layout.py @@ -20,7 +20,7 @@ size in percent, not in pixels. The format is:: widget.size_hint = (width_percent, height_percent) -The percent is specified as a floating point number in the range 0-1. For +The percent is specified as a floating point number in the range 0-1. For example, 0.5 is 50%, 1 is 100%. If you want a widget's width to be half of the parent's width and the diff --git a/kivy/uix/modalview.py b/kivy/uix/modalview.py index 7b49af9e7..1ed15af5b 100644 --- a/kivy/uix/modalview.py +++ b/kivy/uix/modalview.py @@ -4,8 +4,8 @@ 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. +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, deactivate the size_hint and use a specific @@ -30,8 +30,9 @@ 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 :: +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!') @@ -62,7 +63,7 @@ view from closing by explictly returning True from your callback :: ''' -__all__ = ('ModalView',) +__all__ = ('ModalView', ) from kivy.logger import Logger from kivy.animation import Animation @@ -78,16 +79,16 @@ class ModalView(AnchorLayout): `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. + 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. + :data:`auto_dismiss` is a :class:`~kivy.properties.BooleanProperty`, + default to True. ''' attach_to = ObjectProperty(None) From f197174d51f92f207c40253b51c9ff77df150352 Mon Sep 17 00:00:00 2001 From: tshirtman Date: Mon, 30 Jul 2012 10:10:46 +0200 Subject: [PATCH 70/86] fix qwerty layout closes #598 --- kivy/data/keyboards/qwerty.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/kivy/data/keyboards/qwerty.json b/kivy/data/keyboards/qwerty.json index 9127ba467..d1dac3c97 100644 --- a/kivy/data/keyboards/qwerty.json +++ b/kivy/data/keyboards/qwerty.json @@ -7,28 +7,28 @@ ["`", "`", "`", 1], ["1", "1", "1", 1], ["2", "2", "2", 1], ["3", "3", "3", 1], ["4", "4", "4", 1], ["5", "5", "5", 1], ["6", "6", "6", 1], ["7", "7", "7", 1], ["8", "8", "8", 1], - ["9", "9", "9", 1], ["0", "0", "0", 1], ["+", "+", "+", 1], + ["9", "9", "9", 1], ["0", "0", "0", 1], ["-", "-", "-", 1], ["=", "=", "=", 1], ["\u232b", null, "backspace", 2] ], "normal_2" : [ ["\u21B9", "\t", "tab", 1.5], ["q", "q", "q", 1], ["w", "w", "w", 1], ["e", "e", "e", 1], ["r", "r", "r", 1], ["t", "t", "t", 1], ["y", "y", "y", 1], ["u", "u", "u", 1], ["i", "i", "i", 1], - ["o", "o", "o", 1], ["p", "p", "p", 1], ["{", "{", "{", 1], - ["}", "}", "}", 1], ["|", "|", "|", 1.5] + ["o", "o", "o", 1], ["p", "p", "p", 1], ["[", "[", "[", 1], + ["]", "]", "j", 1], ["\\", "\\", "\\", 1] ], "normal_3": [ ["\u21ea", null, "capslock", 1.8], ["a", "a", "a", 1], ["s", "s", "s", 1], ["d", "d", "d", 1], ["f", "f", "f", 1], ["g", "g", "g", 1], ["h", "h", "h", 1], ["j", "j", "j", 1], ["k", "k", "k", 1], - ["l", "l", "l", 1], [":", ":", ":", 1], ["\"", "\"", "\"", 1], + ["l", "l", "l", 1], [":", ":", ":", 1], ["'", "'", "'", 1], ["\u23ce", null, "enter", 2.2] ], "normal_4": [ ["\u21e7", null, "shift", 2.5], ["z", "z", null, 1], ["x", "x", "x", 1], ["c", "c", "c", 1], ["v", "v", "v", 1], ["b", "b", "b", 1], - ["n", "n", "n", 1], ["m", "m", "m", 1], ["<", "<", "<", 1], - [">", ">", ">", 1], ["?", "?", "?", 1], ["\u21e7", null, "shift", 2.5] + ["n", "n", "n", 1], ["m", "m", "m", 1], [",", ",", ",", 1], + [".", ".", ".", 1], ["/", "/", "/", 1], ["\u21e7", null, "shift", 2.5] ], "normal_5": [ [" ", " ", "spacebar", 12], ["\u2b12", null, "layout", 1.5], ["\u2a2f", null, "escape", 1.5] @@ -44,21 +44,21 @@ ["\u21B9", "\t", "tab", 1.5], ["Q", "Q", null, 1], ["W", "W", null, 1], ["E", "E", "e", 1], ["R", "R", "r", 1], ["T", "T", "t", 1], ["Y", "Y", "y", 1], ["U", "U", "u", 1], ["I", "I", "i", 1], - ["O", "O", "o", 1], ["P", "P", "p", 1], ["[", "[", "[", 1], - ["]", "]", "j", 1], ["?", "?", "?", 1.5] + ["O", "O", "o", 1], ["P", "P", "p", 1], ["{", "{", "{", 1], + ["}", "}", "}", 1], ["|", "|", "|", 1.5] ], "shift_3": [ ["\u21ea", null, "capslock", 1.8], ["A", "A", "a", 1], ["S", "S", "s", 1], ["D", "D", "d", 1], ["F", "F", "f", 1], ["G", "G", "g", 1], ["H", "H", "h", 1], ["J", "J", "j", 1], ["K", "K", "k", 1], - ["L", "L", "l", 1], [":", ":", ":", 1], ["'", "'", "'", 1], + ["L", "L", "l", 1], [";", ";", ";", 1], ["\"", "\"", "\"", 1], ["\u23ce", null, "enter", 2.2] ], "shift_4": [ ["\u21e7", null, "shift", 2.5], ["Z", "Z", "z", 1], ["X", "X", "x", 1], ["C", "C", "c", 1], ["V", "V", "v", 1], ["B", "B", "b", 1], - ["N", "N", "n", 1], ["M", "M", "m", 1], [",", ",", ",", 1], - [".", ".", ".", 1], ["/", "/", "/", 1], ["\u21e7", null, "shift", 2.5] + ["N", "N", "n", 1], ["M", "M", "m", 1], ["<", "<", "<", 1], + [">", ">", ">", 1], ["?", "?", "?", 1.5], ["\u21e7", null, "shift", 2.5] ], "shift_5": [ [" ", " ", "spacebar", 12], ["\u2b12", null, "layout", 1.5], ["\u2a2f", null, "escape", 1.5] From b68cdd69aeef0b10fd2456bca3d8a4656288dd69 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Mon, 30 Jul 2012 16:30:10 +0200 Subject: [PATCH 71/86] fix BoundedNumericProperty.set_max. closes #599 --- kivy/properties.pyx | 6 +++--- kivy/tests/test_issue_599.py | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 kivy/tests/test_issue_599.py diff --git a/kivy/properties.pyx b/kivy/properties.pyx index 6ba56e704..be4d2d64d 100644 --- a/kivy/properties.pyx +++ b/kivy/properties.pyx @@ -666,10 +666,10 @@ cdef class BoundedNumericProperty(Property): ''' cdef dict s = obj.__storage[self._name] if value is None: - s['use_min'] = 0 + s['use_max'] = 0 else: - s['min'] = value - s['use_min'] = 1 + s['max'] = value + s['use_max'] = 1 def get_max(self, obj): '''Return the maximum value acceptable for the BoundedNumericProperty in diff --git a/kivy/tests/test_issue_599.py b/kivy/tests/test_issue_599.py new file mode 100644 index 000000000..c369ef251 --- /dev/null +++ b/kivy/tests/test_issue_599.py @@ -0,0 +1,21 @@ +import unittest +from kivy.event import EventDispatcher +from kivy.properties import BoundedNumericProperty + + +class PropertyWidget(EventDispatcher): + foo = BoundedNumericProperty(1, min=-5, max=5) + + +class Issue599(unittest.TestCase): + + def test_minmax(self): + wid = PropertyWidget() + + self.assertEqual(wid.property('foo').get_min(wid), -5) + wid.property('foo').set_min(wid, 0) + self.assertEqual(wid.property('foo').get_min(wid), 0) + + self.assertEqual(wid.property('foo').get_max(wid), 5) + wid.property('foo').set_max(wid, 10) + self.assertEqual(wid.property('foo').get_max(wid), 10) From 5f2af7cc8dc35ec3abd44b8ae0fdb63e35b4de50 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Mon, 30 Jul 2012 16:35:51 +0200 Subject: [PATCH 72/86] use the real EventDispatcher instead of a fake class --- kivy/tests/test_properties.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/kivy/tests/test_properties.py b/kivy/tests/test_properties.py index 4db18bb75..162da7bf7 100644 --- a/kivy/tests/test_properties.py +++ b/kivy/tests/test_properties.py @@ -3,19 +3,11 @@ Test properties attached to a widget ''' import unittest +from kivy.event import EventDispatcher - -class Widget(object): - '''Fake widget class''' - - def __init__(self, **kwargs): - super(Widget, self).__init__(**kwargs) - self.__dict__['__uid'] = 1 - self.__dict__['__storage'] = {} - - -wid = Widget() - +class TestProperty(EventDispatcher): + pass +wid = TestProperty() class PropertiesTestCase(unittest.TestCase): From 9f52e5752df6e316977e2996ec5b031ef8e4462e Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Mon, 30 Jul 2012 19:27:36 +0200 Subject: [PATCH 73/86] properties: fix unbind() method that doesn't work with bounded methods --- kivy/properties.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kivy/properties.pyx b/kivy/properties.pyx index be4d2d64d..7d57d5c25 100644 --- a/kivy/properties.pyx +++ b/kivy/properties.pyx @@ -244,7 +244,7 @@ cdef class Property: ''' cdef list observers = obj.__storage[self._name]['observers'] for obj in observers[:]: - if obj is observer: + if obj == observer: observers.remove(obj) def __set__(self, obj, val): From 82d3595859ec3ef1df1078363dad1eada63de333 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Tue, 31 Jul 2012 01:58:04 +0200 Subject: [PATCH 74/86] dropdown: first implementation of a dropdown widget. --- kivy/factory_registers.py | 1 + kivy/uix/dropdown.py | 300 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100644 kivy/uix/dropdown.py diff --git a/kivy/factory_registers.py b/kivy/factory_registers.py index 93d274cce..7a6b95eef 100644 --- a/kivy/factory_registers.py +++ b/kivy/factory_registers.py @@ -81,6 +81,7 @@ r('Bubble', module='kivy.uix.bubble') r('BubbleButton', module='kivy.uix.bubble') r('Camera', module='kivy.uix.camera') r('CheckBox', module='kivy.uix.checkbox') +r('DropDown', module='kivy.uix.dropdown') r('FloatLayout', module='kivy.uix.floatlayout') r('RelativeLayout', module='kivy.uix.relativelayout') r('FileChooserListView', module='kivy.uix.filechooser') diff --git a/kivy/uix/dropdown.py b/kivy/uix/dropdown.py new file mode 100644 index 000000000..6a9ecfa21 --- /dev/null +++ b/kivy/uix/dropdown.py @@ -0,0 +1,300 @@ +''' +Drop-Down List +============== + +.. versionadded:: 1.4.0 + +A versatile drop-down list, that can be used with custom widget. It allow you to +display a list of widgets under a displayed widget. Unlike others toolkits, the +list of widgets is what you want, it can be simple button, or images etc. + +The positionning of the drop-down list is fully automatic: we will always try to +place the dropdown list in a way that the user can select an item in the list. + +Basic example +------------- + +A button with a dropdown list of 10 possibles values. All the button within the +dropdown list will trigger the dropdown :meth:`DropDown.select` method. And +then, the mainbutton text will display the selection of the dropdown. :: + + from kivy.uix.dropdown import DropDown + from kivy.uix.button import Button + from functools import partial + + # create a dropdown with 10 button + dropdown = DropDown() + for index in xrange(10): + btn = Button(text='Value %d' % index, size_hint_y=None, height=44) + + # for each button, attach a callback that will call the select() method + # on the dropdown. We'll pass the text of the button as the data of the + # selection. + btn.bind(on_release=partial(dropdown.select, btn.text)) + + # then add the button inside the dropdown + dropdown.add_widget(btn) + + # create a big main button + mainbutton = Button(text='Hello', size_hint=(None, None)) + + # show the dropdown menu when the main button is released + # note: all the bind() always pass the instance of the caller (here, the + # mainbutton instance) as first argument of the callback (here, + # dropdown.open.). + mainbutton.bind(on_release=dropdown.open) + + # one last thing, listen to the selection done in the dropdown list. assign + # the data to the button text. + dropdown.bind(on_select=lambda instance, x: setattr(mainbutton, 'text', x)) + + +Extending dropdown in Kv +------------------------ + +You could create a dropdown directly from kv:: + + #:kivy 1.4.0 + : + Button: + text: 'My first Item' + size_hint_y: None + height: 44 + on_release: root.select('item1') + Label: + text: 'Unselectable item' + size_hint_y: None + height: 44 + Button: + text: 'My second Item' + size_hint_y: None + height: 44 + on_release: root.select('item2') + +And then, create the associated python class, and use it:: + + class CustomDropDown(DropDown): + pass + + dropdown = CustomDropDown() + mainbutton = Button(text='Hello', size_hint=(None, None)) + mainbutton.bind(on_release=dropdown.open) + dropdown.bind(on_select=lambda instance, x: setattr(mainbutton, 'text', x)) +''' + +__all__ = ('DropDown', ) + +from kivy.uix.scrollview import ScrollView +from kivy.properties import ObjectProperty, NumericProperty, BooleanProperty +from kivy.lang import Builder + +Builder.load_string(''' +: + container: container + do_scroll_x: False + size_hint: None, None + + GridLayout: + id: container + size_hint_y: None + height: self.minimum_size[1] + cols: 1 +''') + + +class DropDownException(Exception): + '''DropDownException class. + ''' + pass + + +class DropDown(ScrollView): + '''DropDown class. See module documentation for more information. + + :Events: + `on_select`: data + Fired when a selection is done, with the data of the selection as + first argument. Data is what you pass in the :meth:`select` method + as first argument. + ''' + + auto_width = BooleanProperty(True) + '''By default, the width of the dropdown will be the same as the width of + the attached widget. Set to False if you want to provide your own width. + ''' + + max_height = NumericProperty(None, allownone=True) + '''Indicate the maximum height that the dropdown can take. If None, it will + take the maximum height available, until the top or bottom of the screen + will be reached. + + :data:`max_height` is a :class:`~kivy.properties.NumericProperty`, default + to None. + ''' + + dismiss_on_select = BooleanProperty(True) + '''By default, the dropdown will be automatically dismissed when a selection + have been done. Set to False to prevent the dismiss. + + :data:`dismiss_on_select` is a :class:`~kivy.properties.BooleanProperty`, + default to True. + ''' + + attach_to = ObjectProperty(allownone=True) + '''(internal) Property that will be set to the widget on which the drop down + list is attached to. + + The method :meth:`open` will automatically set that property, while + :meth:`dismiss` will set back to None. + ''' + + container = ObjectProperty() + '''(internal) Property that will be set to the container of the dropdown + list, which is a :class:`~kivy.uix.gridlayout.GridLayout` by default. + ''' + + def __init__(self, **kwargs): + self._win = None + self.register_event_type('on_select') + super(DropDown, self).__init__(**kwargs) + self.container.bind(minimum_size=self._container_minimum_size) + self.bind(size=self._reposition) + + def open(self, widget): + '''Open the dropdown list, and attach to a specific widget. + Depending the position of the widget on the window and the height of the + dropdown, the placement might be lower or upper to that widget. + ''' + # ensure we are not already attached + if self.attach_to is not None: + self.dismiss() + + # we will attach ourself to the main window, so ensure the widget we are + # looking for have a window + self._win = widget.get_parent_window() + if self._win is None: + raise DropDownException( + 'Cannot open a dropdown list on a hidden widget') + + self.attach_to = widget + widget.bind(pos=self._reposition, size=self._reposition) + self._reposition() + + # attach ourself to the main window + self._win.add_widget(self) + + def dismiss(self, *largs): + '''Remove the dropdown widget from the iwndow, and detach itself from + the attached widget. + ''' + if self.parent: + self.parent.remove_widget(self) + if self.attach_to: + self.attach_to.unbind(pos=self._reposition, size=self._reposition) + self.attach_to = None + + def select(self, data, *ignored): + '''Call this method to trigger the `on_select` event, with the selection + (can be anything you want.) + ''' + self.dispatch('on_select', data) + if self.dismiss_on_select: + self.dismiss() + + def on_select(self, data): + pass + + def _container_minimum_size(self, instance, size): + if self.max_height: + self.height = min(size[1], self.max_height) + self.do_scroll_y = size[1] > self.max_height + else: + self.height = size[1] + self.do_scroll_y = True + + def add_widget(self, *largs): + if self.container: + return self.container.add_widget(*largs) + return super(DropDown, self).add_widget(*largs) + + def remove_widget(self, *largs): + if self.container: + return self.container.remove_widget(*largs) + return super(DropDown, self).remove_widget(*largs) + + def on_touch_down(self, touch): + if super(DropDown, self).on_touch_down(touch): + return True + if self.collide_point(*touch.pos): + return True + self.dismiss() + + def on_touch_up(self, touch): + if super(DropDown, self).on_touch_up(touch): + return True + self.dismiss() + + def _reposition(self, *largs): + # calculate the coordinate of the attached widget in the window + # coordinate sysem + win = self._win + widget = self.attach_to + print win, widget + if not widget or not win: + return + wx, wy = widget.to_window(*widget.pos) + wtop, wright = widget.to_window(widget.top, widget.right) + + # set width and x + if self.auto_width: + self.width = wright - wx + + # ensure the dropdown list doesn't get out on the X axis, with a + # preference to 0 in case the list is too wide. + x = wx + if x + self.width > win.width: + x = win.width - self.width + if x < 0: + x = 0 + self.x = x + + # determine if we display the dropdown upper or lower to the widget + h_bottom = wy - self.height + h_top = win.height - (wtop + self.height) + if h_bottom > 0: + self.top = wy + elif h_top > 0: + self.y = wtop + else: + # none of both top/bottom have enough place to display the widget at + # the current size. Take the best side, and fit to it. + height = max(h_bottom, h_top) + if height == h_bottom: + self.top = wy + self.height = wy + else: + self.y = wtop + self.height = win.height - wtop + + +if __name__ == '__main__': + from kivy.uix.button import Button + from kivy.base import runTouchApp + from functools import partial + + def show_dropdown(button, *largs): + dp = DropDown() + dp.bind(on_select=lambda instance, x: setattr(button, 'text', x)) + for i in xrange(10): + item = Button(text='hello %d' % i, size_hint_y=None, height=44) + item.bind(on_release=partial(dp.select, item.text)) + dp.add_widget(item) + dp.open(button) + + def touch_move(instance, touch): + instance.center = touch.pos + + btn = Button(text='SHOW', size_hint=(None, None), pos=(300, 200)) + btn.bind(on_release=show_dropdown, on_touch_move=touch_move) + + runTouchApp(btn) From 0da37fc8a584769d376885cae789c1efb4e5e195 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Tue, 31 Jul 2012 01:59:05 +0200 Subject: [PATCH 75/86] remove debug --- kivy/uix/dropdown.py | 1 - 1 file changed, 1 deletion(-) diff --git a/kivy/uix/dropdown.py b/kivy/uix/dropdown.py index 6a9ecfa21..09868c6ea 100644 --- a/kivy/uix/dropdown.py +++ b/kivy/uix/dropdown.py @@ -239,7 +239,6 @@ class DropDown(ScrollView): # coordinate sysem win = self._win widget = self.attach_to - print win, widget if not widget or not win: return wx, wy = widget.to_window(*widget.pos) From 2a802a096cb65ecefc3d3fda5a518dfc9134dbaa Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Tue, 31 Jul 2012 11:56:31 +0200 Subject: [PATCH 76/86] fix selection->data doc --- kivy/uix/dropdown.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kivy/uix/dropdown.py b/kivy/uix/dropdown.py index 09868c6ea..658822f06 100644 --- a/kivy/uix/dropdown.py +++ b/kivy/uix/dropdown.py @@ -194,8 +194,8 @@ class DropDown(ScrollView): self.attach_to = None def select(self, data, *ignored): - '''Call this method to trigger the `on_select` event, with the selection - (can be anything you want.) + '''Call this method to trigger the `on_select` event, with the `data` + selection. The `data` can be anything you want. ''' self.dispatch('on_select', data) if self.dismiss_on_select: From 82eb0051f457e5f70c5424d8901c0dc2ea64e654 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Tue, 31 Jul 2012 16:02:51 +0200 Subject: [PATCH 77/86] spinner: introduce new Spinner widget: A view that displays one child at a time and lets the user pick among them. Made only for text. (this replace the combobox pull request, and its based on the dropdown widget.) --- doc/sources/images/spinner.jpg | Bin 0 -> 6893 bytes examples/widgets/spinner.py | 15 ++ kivy/data/images/defaulttheme-0.png | Bin 43120 -> 43303 bytes kivy/data/images/defaulttheme.atlas | 2 +- kivy/factory_registers.py | 1 + kivy/tools/theming/defaulttheme/spinner.png | Bin 0 -> 391 bytes .../theming/defaulttheme/spinner_pressed.png | Bin 0 -> 386 bytes kivy/uix/dropdown.py | 5 + kivy/uix/spinner.py | 132 ++++++++++++++++++ 9 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 doc/sources/images/spinner.jpg create mode 100644 examples/widgets/spinner.py create mode 100644 kivy/tools/theming/defaulttheme/spinner.png create mode 100644 kivy/tools/theming/defaulttheme/spinner_pressed.png create mode 100644 kivy/uix/spinner.py diff --git a/doc/sources/images/spinner.jpg b/doc/sources/images/spinner.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e1c309a15f621ddef25a401e1a02031507a0c3b0 GIT binary patch literal 6893 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 LHEx8-T~GfPxG5>O literal 0 HcmV?d00001 diff --git a/examples/widgets/spinner.py b/examples/widgets/spinner.py new file mode 100644 index 000000000..23a0e808a --- /dev/null +++ b/examples/widgets/spinner.py @@ -0,0 +1,15 @@ +from kivy.uix.spinner import Spinner +from kivy.base import runTouchApp + +spinner = Spinner( + text='Home', + values=('Home', 'Work', 'Other', 'Custom'), + size_hint=(None, None), size=(100, 44), + pos_hint={'center_x': .5, 'center_y': .5}) + +def show_selected_value(spinner, text): + print 'The spinner', spinner, 'have text', text + +spinner.bind(text=show_selected_value) + +runTouchApp(spinner) diff --git a/kivy/data/images/defaulttheme-0.png b/kivy/data/images/defaulttheme-0.png index 4d3b358d8f33c7325f22a3f7d7b88f6160e91a0d..070430af82862b4c747445ada12b065a8c2623c7 100644 GIT binary patch delta 4390 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 delta 4206 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 Eg35=dbN~PV diff --git a/kivy/data/images/defaulttheme.atlas b/kivy/data/images/defaulttheme.atlas index 21a3377c6..0588cc653 100644 --- a/kivy/data/images/defaulttheme.atlas +++ b/kivy/data/images/defaulttheme.atlas @@ -1 +1 @@ -{"defaulttheme-0.png": {"player-play-overlay": [306, 396, 117, 115], "progressbar_background": [160, 137, 24, 24], "media-playback-pause": [448, 344, 48, 48], "tab_btn_pressed": [465, 178, 32, 32], "image-missing": [399, 344, 48, 48], "filechooser_selected": [187, 393, 118, 118], "audio-volume-muted": [350, 344, 48, 48], "sliderv_background": [473, 404, 37, 41], "tab": [332, 228, 96, 32], "close": [490, 491, 20, 20], "ring": [1, 326, 185, 185], "vkeyboard_key_down": [61, 129, 32, 32], "vkeyboard_background": [187, 328, 64, 64], "checkbox_off": [300, 178, 32, 32], "bubble_arrow": [148, 162, 16, 10], "player-background": [228, 222, 103, 103], "bubble": [424, 446, 65, 65], "sliderh_background": [148, 173, 41, 37], "audio-volume-medium": [301, 344, 48, 48], "media-playback-start": [1, 162, 48, 48], "tab_btn": [432, 178, 32, 32], "bubble_btn_pressed": [267, 178, 32, 32], "tree_closed": [490, 470, 20, 20], "switch-background": [429, 228, 83, 32], "filechooser_file": [332, 261, 64, 64], "checkbox_radio_off": [366, 178, 32, 32], "vkeyboard_key_normal": [94, 129, 32, 32], "checkbox_radio_on": [399, 178, 32, 32], "checkbox_on": [333, 178, 32, 32], "tree_opened": [490, 449, 20, 20], "button_pressed": [31, 124, 29, 37], "media-playback-stop": [50, 162, 48, 48], "audio-volume-high": [424, 397, 48, 48], "audio-volume-low": [252, 344, 48, 48], "bubble_btn": [234, 178, 32, 32], "slider_cursor": [99, 162, 48, 48], "button": [1, 124, 29, 37], "progressbar": [127, 137, 32, 24], "switch-button": [190, 178, 43, 32], "filechooser_folder": [397, 261, 64, 64], "popup-background": [462, 271, 45, 54], "modalview-background": [462, 271, 45, 54], "textinput_active": [1, 211, 114, 114], "textinput": [116, 214, 111, 111]}} \ No newline at end of file +{"defaulttheme-0.png": {"player-play-overlay": [306, 396, 117, 115], "spinner_pressed": [91, 124, 29, 37], "progressbar_background": [220, 137, 24, 24], "media-playback-pause": [448, 344, 48, 48], "tab_btn_pressed": [465, 178, 32, 32], "image-missing": [399, 344, 48, 48], "filechooser_selected": [187, 393, 118, 118], "audio-volume-muted": [350, 344, 48, 48], "sliderv_background": [473, 404, 37, 41], "tab": [332, 228, 96, 32], "close": [490, 491, 20, 20], "ring": [1, 326, 185, 185], "vkeyboard_key_down": [121, 129, 32, 32], "vkeyboard_background": [187, 328, 64, 64], "checkbox_off": [300, 178, 32, 32], "bubble_arrow": [148, 162, 16, 10], "player-background": [228, 222, 103, 103], "bubble": [424, 446, 65, 65], "spinner": [61, 124, 29, 37], "sliderh_background": [148, 173, 41, 37], "audio-volume-medium": [301, 344, 48, 48], "media-playback-start": [1, 162, 48, 48], "tab_btn": [432, 178, 32, 32], "bubble_btn_pressed": [267, 178, 32, 32], "tree_closed": [490, 470, 20, 20], "switch-background": [429, 228, 83, 32], "filechooser_file": [332, 261, 64, 64], "checkbox_radio_off": [366, 178, 32, 32], "vkeyboard_key_normal": [154, 129, 32, 32], "checkbox_radio_on": [399, 178, 32, 32], "checkbox_on": [333, 178, 32, 32], "tree_opened": [490, 449, 20, 20], "button_pressed": [31, 124, 29, 37], "media-playback-stop": [50, 162, 48, 48], "audio-volume-high": [424, 397, 48, 48], "audio-volume-low": [252, 344, 48, 48], "bubble_btn": [234, 178, 32, 32], "slider_cursor": [99, 162, 48, 48], "button": [1, 124, 29, 37], "progressbar": [187, 137, 32, 24], "switch-button": [190, 178, 43, 32], "filechooser_folder": [397, 261, 64, 64], "popup-background": [462, 271, 45, 54], "textinput_active": [1, 211, 114, 114], "textinput": [116, 214, 111, 111]}} \ No newline at end of file diff --git a/kivy/factory_registers.py b/kivy/factory_registers.py index 7a6b95eef..6e469bb29 100644 --- a/kivy/factory_registers.py +++ b/kivy/factory_registers.py @@ -100,6 +100,7 @@ r('Settings', module='kivy.uix.settings') r('Slider', module='kivy.uix.slider') r('Screen', module='kivy.uix.screenmanager') r('ScreenManager', module='kivy.uix.screenmanager') +r('Spinner', module='kivy.uix.spinner') r('StackLayout', module='kivy.uix.stacklayout') r('StencilView', module='kivy.uix.stencilview') r('Switch', module='kivy.uix.switch') diff --git a/kivy/tools/theming/defaulttheme/spinner.png b/kivy/tools/theming/defaulttheme/spinner.png new file mode 100644 index 0000000000000000000000000000000000000000..e7a45ac1eb491f93a743a14de85246437525c2a6 GIT binary patch literal 391 zcmeAS@N?(olHy`uVBq!ia0vp^vOuiL!3HGv?Rs<`NHG=%xjQkeJ16rJ$YD$Jc6VX; z4}uH!E}sk(;VkfoEM{Qf?gU{*^OL970tMMiJbhi+@371BYUna+^ehCL!tUwf7!q;# z?e)FBM;rv&9+potjo|Z$VGp%X-ZRDN#c?4+(H)!_2Y4gC{c?}`aDLJp{uaLikGRQi z#Qi>HxEUYha0nDB&zxn)u>G9n@neF5jJH;;nzu=(`s#tudC&E|G}mmcFc1`cWRVs* z&D|l}f&Z|Bh-;h!!*iKyQO62dE^rAvpJV<(yT-)jBR^+`1GChH1~!ugjJz+>cdffE zzV`L3ZMol_U+-G>{`cQwzh%Gl&12rX$oKLb*1ZdXq*7xRMRFG3$$@;+{iWm?zA zG{>+lbJm`w&o=A3pPCpiM%07Hqv)78&qol`;+08MzBMgRZ+ literal 0 HcmV?d00001 diff --git a/kivy/tools/theming/defaulttheme/spinner_pressed.png b/kivy/tools/theming/defaulttheme/spinner_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..77136b60932723dd04773daae07a31fc963e84b7 GIT binary patch literal 386 zcmeAS@N?(olHy`uVBq!ia0vp^vOuiL!3HGv?Rs<`NHG=%xjQkeJ16rJ$YD$Jc6VX; z4}uH!E}sk(;VkfoEM{Qf?gU{*^OL970tMMiJbhi+@371BYVz#}IWq}p3X`XcV@Sl| zx7Q85m>oshKjx=1r*W^<$;sil!EM=`koi{Drd|C5M_H0)1xxS~mW`ecA|*a$YMW1Q z`mCe0#zR5VDB1WvYu$$jqW^gwJj%4Pv3zlV;>ubl)qORQA>sYck1v*MsGQq-OrEv$ z^+bj^wl_~-Y2@EAp0G9`aD{_H14HTSk9O=1j2#{ZAIxFVdQ&MBb@05ubu%K!iX literal 0 HcmV?d00001 diff --git a/kivy/uix/dropdown.py b/kivy/uix/dropdown.py index 658822f06..81148a06b 100644 --- a/kivy/uix/dropdown.py +++ b/kivy/uix/dropdown.py @@ -222,6 +222,11 @@ class DropDown(ScrollView): return self.container.remove_widget(*largs) return super(DropDown, self).remove_widget(*largs) + def clear_widgets(self): + if self.container: + return self.container.clear_widgets() + return super(DropDown, self).clear_widgets() + def on_touch_down(self, touch): if super(DropDown, self).on_touch_down(touch): return True diff --git a/kivy/uix/spinner.py b/kivy/uix/spinner.py new file mode 100644 index 000000000..93457d158 --- /dev/null +++ b/kivy/uix/spinner.py @@ -0,0 +1,132 @@ +''' +Spinner +======= + +.. versionadded:: 1.4.0 + +.. image:: images/spinner.jpg + :align: right + +Spinner is a widget that provide a quick way to select one value from a set. In +the default state, a spinner show its currently selected value. Touching the +spinner displays a dropdown menu with all other available values. from which the +user can select a new one. + +Example:: + + from kivy.base import runTouchApp + from kivy.uix.spinner import Spinner + + spinner = Spinner( + # default value showed + text='Home', + # available values + values=('Home', 'Work', 'Other', 'Custom'), + # just for positioning in our example + size_hint=(None, None), + size=(100, 44), + pos_hint={'center_x': .5, 'center_y': .5}) + + def show_selected_value(spinner, text): + print 'The spinner', spinner, 'have text', text + + spinner.bind(text=show_selected_value) + + runTouchApp(spinner) + +''' + +__all__ = ('Spinner', 'SpinnerOption') + +from functools import partial +from kivy.properties import ListProperty, ObjectProperty +from kivy.uix.button import Button +from kivy.uix.dropdown import DropDown +from kivy.lang import Builder + + +Builder.load_string(''' +: + size_hint_y: None + height: 44 + +: + background_normal: 'atlas://data/images/defaulttheme/spinner' + background_down: 'atlas://data/images/defaulttheme/spinner_pressed' +''') + + +class SpinnerOption(Button): + '''Special button used in the dropdown list. We just set the default + size_hint_y and height. + ''' + pass + + +class Spinner(Button): + '''Spinner class, see module documentation for more information + ''' + + values = ListProperty() + '''Values that can be selected by the user. It must be a list of strings. + + :data:`values` is a :class:`~kivy.properties.ListProperty`, default to []. + ''' + + option_cls = ObjectProperty(SpinnerOption) + '''Class used to display the options within the dropdown list displayed + under the Spinner. The `text` property in the class will represent the + value. + + The option class require at least: + + - one `text` property where the value will be put + - one `on_release` event that you need to trigger when the option is + touched. + + :data:`option_cls` is a :class:`~kivy.properties.ObjectProperty`, default + to :class:`SpinnerOption`. + ''' + + dropdown_cls = ObjectProperty(DropDown) + '''Class used to display the dropdown list when the Spinner is pressed. + + :data:`dropdown_cls` is a :class:`~kivy.properties.ObjectProperty`, default + to :class:`~kivy.uix.dropdown.DropDown`. + ''' + + def __init__(self, **kwargs): + self._dropdown = None + super(Spinner, self).__init__(**kwargs) + self.bind( + on_release=self._open_dropdown, + dropdown_cls=self._build_dropdown, + option_cls=self._build_dropdown, + values=self._update_dropdown) + self._build_dropdown() + + def _build_dropdown(self, *largs): + if self._dropdown: + self._dropdown.unbind(on_select=self._on_dropdown_select) + self._dropdown.dismiss() + self._dropdown = None + self._dropdown = self.dropdown_cls() + self._dropdown.bind(on_select=self._on_dropdown_select) + self._update_dropdown() + + def _update_dropdown(self, *largs): + dp = self._dropdown + cls = self.option_cls + + dp.clear_widgets() + for value in self.values: + item = cls(text=value) + item.bind(on_release=partial(dp.select, value)) + dp.add_widget(item) + + def _open_dropdown(self, *largs): + self._dropdown.open(self) + + def _on_dropdown_select(self, instance, data, *largs): + self.text = data + From 0167a5e4ca3f6723022befcac6b206af9a2fa8d1 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Tue, 31 Jul 2012 16:28:43 +0200 Subject: [PATCH 78/86] spinner: add spinner in the showcase example --- examples/demo/showcase/showcase.kv | 23 +++++++++++++++-------- kivy/uix/__init__.py | 3 ++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/examples/demo/showcase/showcase.kv b/examples/demo/showcase/showcase.kv index 386f198b6..729b03088 100644 --- a/examples/demo/showcase/showcase.kv +++ b/examples/demo/showcase/showcase.kv @@ -255,41 +255,48 @@ TextInput: text: 'Monoline textinput' size_hint_y: None - height: 50 + height: 30 TextInput: text: 'This is a password' size_hint_y: None - height: 50 + height: 30 password: True TextInput: text: 'Readonly textinput' size_hint_y: None - height: 50 + height: 30 readonly: True TextInput: text: 'Multiline textinput\nSecond line' + HSeparator: + text: 'Spinner' + + Spinner: + size_hint_y: None + height: 44 + values: ('Work', 'Home', 'Other', 'Custom') + text: 'Home' + HSeparator: text: 'Checkbox' GridLayout: rows: 1 - CheckBox + CheckBox: + active: True CheckBox GridLayout: cols: 2 CheckBox: group: 'group1' + active: True CheckBox: group: 'group1' - CheckBox: - group: 'group2' - CheckBox: - group: 'group2' diff --git a/kivy/uix/__init__.py b/kivy/uix/__init__.py index 18fc08443..d4e3b709e 100644 --- a/kivy/uix/__init__.py +++ b/kivy/uix/__init__.py @@ -28,8 +28,9 @@ Read first: :doc:`api-kivy.uix.widget` combinations. We call them complex because the assembly and usages are not as generic as the classicals widgets. - :doc:`api-kivy.uix.bubble`, + :doc:`api-kivy.uix.bubble`, :doc:`api-kivy.uix.dropdown`, :doc:`api-kivy.uix.filechooser`, :doc:`api-kivy.uix.popup`, + :doc:`api-kivy.uix.spinner`, :doc:`api-kivy.uix.tabbedpanel`, :doc:`api-kivy.uix.videoplayer`, :doc:`api-kivy.uix.vkeyboard`, From 45eef0702c3e306ce3ae58278ed61ed4dc31bbba Mon Sep 17 00:00:00 2001 From: Qua-non Date: Wed, 1 Aug 2012 03:14:57 +0530 Subject: [PATCH 79/86] loader.py fix path for image-missing.png --- kivy/loader.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kivy/loader.py b/kivy/loader.py index 5b5e225c9..35e1041aa 100644 --- a/kivy/loader.py +++ b/kivy/loader.py @@ -21,7 +21,7 @@ If you want to change the default loading image, you can do:: __all__ = ('Loader', 'LoaderBase', 'ProxyImage') -from kivy import kivy_data_dir +from kivy import kivy_data_dir, kivy_base_dir from kivy.logger import Logger from kivy.clock import Clock from kivy.cache import Cache @@ -96,7 +96,8 @@ class LoaderBase(object): def error_image(self): '''Image used for error (readonly)''' if not self._error_image: - error_png_fn = join(kivy_data_dir, 'images', 'image-missing.png') + error_png_fn = join('atlas://', 'data', 'images', 'defaulttheme', + 'image-missing') self._error_image = ImageLoader.load(filename=error_png_fn) return self._error_image From 9299f0d62e1614c0130a6d3509f7b143e1c56a60 Mon Sep 17 00:00:00 2001 From: Qua-non Date: Wed, 1 Aug 2012 03:57:21 +0530 Subject: [PATCH 80/86] loader.py revert to corect path of non-atlas based image using atlas for image-missing has issues with AsyncImage --- kivy/loader.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kivy/loader.py b/kivy/loader.py index 35e1041aa..3c400d245 100644 --- a/kivy/loader.py +++ b/kivy/loader.py @@ -96,8 +96,8 @@ class LoaderBase(object): def error_image(self): '''Image used for error (readonly)''' if not self._error_image: - error_png_fn = join('atlas://', 'data', 'images', 'defaulttheme', - 'image-missing') + error_png_fn = join(kivy_base_dir, 'tools/theming/defaulttheme', + 'image-missing.png') self._error_image = ImageLoader.load(filename=error_png_fn) return self._error_image From f9dfb393dd535c4b315523a7207dfa75bbc6b66b Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Wed, 1 Aug 2012 02:50:06 +0200 Subject: [PATCH 81/86] scrollview: always accept scrolling event in touch up. closes #601 --- kivy/uix/scrollview.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kivy/uix/scrollview.py b/kivy/uix/scrollview.py index 00ff6d0db..8a0e311e3 100644 --- a/kivy/uix/scrollview.py +++ b/kivy/uix/scrollview.py @@ -387,6 +387,11 @@ class ScrollView(StencilView): else: if self._touch is not touch: super(ScrollView, self).on_touch_up(touch) + + # if we do mouse scrolling, always accept it + if 'button' in touch.profile and touch.button.startswith('scroll'): + return True + return self._get_uid() in touch.ud From c8ac7ade8bdc179c30ce6e1fa7ae879b7e2edf8e Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Tue, 31 Jul 2012 20:09:23 -0500 Subject: [PATCH 82/86] - removed 'ignored' argument from select - replaced partial with lambda --- kivy/uix/dropdown.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kivy/uix/dropdown.py b/kivy/uix/dropdown.py index 81148a06b..f7ec75ee5 100644 --- a/kivy/uix/dropdown.py +++ b/kivy/uix/dropdown.py @@ -1,3 +1,4 @@ +from __future__ import print_function ''' Drop-Down List ============== @@ -193,7 +194,7 @@ class DropDown(ScrollView): self.attach_to.unbind(pos=self._reposition, size=self._reposition) self.attach_to = None - def select(self, data, *ignored): + def select(self, data): '''Call this method to trigger the `on_select` event, with the `data` selection. The `data` can be anything you want. ''' @@ -291,7 +292,7 @@ if __name__ == '__main__': dp.bind(on_select=lambda instance, x: setattr(button, 'text', x)) for i in xrange(10): item = Button(text='hello %d' % i, size_hint_y=None, height=44) - item.bind(on_release=partial(dp.select, item.text)) + item.bind(on_release=lambda button: dp.select(button.text)) dp.add_widget(item) dp.open(button) From a709aa49546b4ab7727be71f8adac9a02bca0c8a Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Tue, 31 Jul 2012 20:29:06 -0500 Subject: [PATCH 83/86] - removed debug imports - updated dropdown documentation - updated spinner to use lambda instead of partial --- kivy/uix/dropdown.py | 9 +++------ kivy/uix/spinner.py | 3 +-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/kivy/uix/dropdown.py b/kivy/uix/dropdown.py index f7ec75ee5..cb2e65ed2 100644 --- a/kivy/uix/dropdown.py +++ b/kivy/uix/dropdown.py @@ -1,4 +1,3 @@ -from __future__ import print_function ''' Drop-Down List ============== @@ -21,7 +20,6 @@ then, the mainbutton text will display the selection of the dropdown. :: from kivy.uix.dropdown import DropDown from kivy.uix.button import Button - from functools import partial # create a dropdown with 10 button dropdown = DropDown() @@ -31,7 +29,7 @@ then, the mainbutton text will display the selection of the dropdown. :: # for each button, attach a callback that will call the select() method # on the dropdown. We'll pass the text of the button as the data of the # selection. - btn.bind(on_release=partial(dropdown.select, btn.text)) + btn.bind(on_release=lambda btn: dropdown.select(btn.text)) # then add the button inside the dropdown dropdown.add_widget(btn) @@ -194,7 +192,7 @@ class DropDown(ScrollView): self.attach_to.unbind(pos=self._reposition, size=self._reposition) self.attach_to = None - def select(self, data): + def select(self, data, *args): '''Call this method to trigger the `on_select` event, with the `data` selection. The `data` can be anything you want. ''' @@ -285,14 +283,13 @@ class DropDown(ScrollView): if __name__ == '__main__': from kivy.uix.button import Button from kivy.base import runTouchApp - from functools import partial def show_dropdown(button, *largs): dp = DropDown() dp.bind(on_select=lambda instance, x: setattr(button, 'text', x)) for i in xrange(10): item = Button(text='hello %d' % i, size_hint_y=None, height=44) - item.bind(on_release=lambda button: dp.select(button.text)) + item.bind(on_release=lambda btn: dp.select(btn.text)) dp.add_widget(item) dp.open(button) diff --git a/kivy/uix/spinner.py b/kivy/uix/spinner.py index 93457d158..2ed45a64f 100644 --- a/kivy/uix/spinner.py +++ b/kivy/uix/spinner.py @@ -38,7 +38,6 @@ Example:: __all__ = ('Spinner', 'SpinnerOption') -from functools import partial from kivy.properties import ListProperty, ObjectProperty from kivy.uix.button import Button from kivy.uix.dropdown import DropDown @@ -121,7 +120,7 @@ class Spinner(Button): dp.clear_widgets() for value in self.values: item = cls(text=value) - item.bind(on_release=partial(dp.select, value)) + item.bind(on_release=lambda option: dp.select(option.text)) dp.add_widget(item) def _open_dropdown(self, *largs): From 4a4449204f04819330cc3c71909e235ddce12161 Mon Sep 17 00:00:00 2001 From: "Edwin Marshall (aspidites)" Date: Tue, 31 Jul 2012 20:40:09 -0500 Subject: [PATCH 84/86] - removed extra arguments left in for debugging... --- kivy/uix/dropdown.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kivy/uix/dropdown.py b/kivy/uix/dropdown.py index cb2e65ed2..94ded676b 100644 --- a/kivy/uix/dropdown.py +++ b/kivy/uix/dropdown.py @@ -192,7 +192,7 @@ class DropDown(ScrollView): self.attach_to.unbind(pos=self._reposition, size=self._reposition) self.attach_to = None - def select(self, data, *args): + def select(self, data): '''Call this method to trigger the `on_select` event, with the `data` selection. The `data` can be anything you want. ''' From a601a6b3c5508073832b8b2a3e0ac492011acc7b Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Wed, 1 Aug 2012 20:43:54 +0200 Subject: [PATCH 85/86] reload: for texture / images, when we are reloading, prevent to use the Cache for storing the temporary image object, as well as the texture created from that Image object. closes #581 --- kivy/core/image/__init__.py | 11 +++++++---- kivy/graphics/context.pyx | 3 +++ kivy/graphics/context_instructions.pyx | 2 ++ kivy/graphics/texture.pyx | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/kivy/core/image/__init__.py b/kivy/core/image/__init__.py index af25e1fee..eb2dcd1a5 100644 --- a/kivy/core/image/__init__.py +++ b/kivy/core/image/__init__.py @@ -136,11 +136,12 @@ class ImageLoaderBase(object): '''Base to implement an image loader.''' __slots__ = ('_texture', '_data', 'filename', 'keep_data', - '_mipmap') + '_mipmap', '_nocache') def __init__(self, filename, **kwargs): self._mipmap = kwargs.get('mipmap', False) self.keep_data = kwargs.get('keep_data', False) + self._nocache = kwargs.get('nocache', False) self.filename = filename self._data = self.load(filename) self._textures = None @@ -166,7 +167,8 @@ class ImageLoaderBase(object): if texture is None: texture = Texture.create_from_data( self._data[count], mipmap=self._mipmap) - Cache.append('kv.texture', uid, texture) + if not self._nocache: + Cache.append('kv.texture', uid, texture) # set as our current texture self._textures.append(texture) @@ -363,7 +365,7 @@ class Image(EventDispatcher): ''' copy_attributes = ('_size', '_filename', '_texture', '_image', - '_mipmap') + '_mipmap', '_nocache') def __init__(self, arg, **kwargs): # this event should be fired on animation of sequenced img's @@ -373,6 +375,7 @@ class Image(EventDispatcher): self._mipmap = kwargs.get('mipmap', False) self._keep_data = kwargs.get('keep_data', False) + self._nocache = kwargs.get('nocache', False) self._size = [0, 0] self._image = None self._filename = None @@ -578,7 +581,7 @@ class Image(EventDispatcher): tmpfilename = self._filename image = ImageLoader.load( self._filename, keep_data=self._keep_data, - mipmap=self._mipmap) + mipmap=self._mipmap, nocache=self._nocache) self._filename = tmpfilename # put the image into the cache if needed diff --git a/kivy/graphics/context.pyx b/kivy/graphics/context.pyx index fa469b351..1a841f413 100644 --- a/kivy/graphics/context.pyx +++ b/kivy/graphics/context.pyx @@ -122,6 +122,7 @@ cdef class Context: cdef Shader shader cdef Canvas canvas + image_objects = Cache._objects['kv.image'] Cache.remove('kv.image') Cache.remove('kv.shader') @@ -171,6 +172,8 @@ cdef class Context: # Restore texture cache texture_objects.update(Cache._objects['kv.texture']) Cache._objects['kv.texture'] = texture_objects + image_objects.update(Cache._objects['kv.image']) + Cache._objects['kv.image'] = image_objects Logger.debug('Context: Reload vbos') for item in self.l_vbo[:]: diff --git a/kivy/graphics/context_instructions.pyx b/kivy/graphics/context_instructions.pyx index 3f314152e..7b3482d82 100644 --- a/kivy/graphics/context_instructions.pyx +++ b/kivy/graphics/context_instructions.pyx @@ -267,6 +267,8 @@ cdef class BindTexture(ContextInstruction): def __set__(self, object texture): if not texture: texture = get_default_texture() + Logger.trace('BindTexture: setting texture %r (previous is %r)' % ( + texture, self._texture)) self._texture = texture property index: diff --git a/kivy/graphics/texture.pyx b/kivy/graphics/texture.pyx index 33042041b..a88810531 100644 --- a/kivy/graphics/texture.pyx +++ b/kivy/graphics/texture.pyx @@ -758,7 +758,7 @@ cdef class Texture: self._id = texture.id else: from kivy.core.image import Image - image = Image(self._source) + image = Image(self._source, nocache=True) self._id = image.texture.id texture = image.texture texture._nofree = 1 From 460cc8ea3c487a8affabefc11bdf3a1fe456fd3b Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Thu, 2 Aug 2012 16:09:46 +0200 Subject: [PATCH 86/86] ios: add entry about how to see the kivy logs/exception + add processcraft in the app store apps --- doc/sources/guide/packaging-ios.rst | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/doc/sources/guide/packaging-ios.rst b/doc/sources/guide/packaging-ios.rst index 2bcb4600f..fbb174c52 100644 --- a/doc/sources/guide/packaging-ios.rst +++ b/doc/sources/guide/packaging-ios.rst @@ -102,6 +102,17 @@ development): FAQ --- +Application quit abnormally! +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, all the print on the console and files are avoided. If you have an +issue when running your application, you can activate the log by commenting the +line in the main.m:: + + putenv("KIVY_NO_CONSOLELOG=1"); + +Then, you should see all the Kivy log on the Xcode console. + How Apple can accept a python app ? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -112,5 +123,7 @@ dynamically loaded. Did you already submit a Kivy application to the App store ? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Yes, check `Defletouch on iTunes `_ +Yes, check: +- `Defletouch on iTunes `_, +- `ProcessCraft on iTunes `_