コード例 #1
0
ファイル: test_properties.py プロジェクト: DanAlbert/kivy
    def test_numericcheck(self):
        from kivy.properties import NumericProperty

        a = NumericProperty()
        a.link(wid, 'a')
        a.link_deps(wid, 'a')
        self.assertEqual(a.get(wid), 0)
        a.set(wid, 99)
        self.assertEqual(a.get(wid), 99)
コード例 #2
0
ファイル: test_properties.py プロジェクト: 13768324554/kivy
    def test_numeric_string_without_units(self):
        from kivy.properties import NumericProperty

        a = NumericProperty()
        a.link(wid, 'a')
        a.link_deps(wid, 'a')
        self.assertEqual(a.get(wid), 0)

        a.set(wid, '2')
        self.assertEqual(a.get(wid), 2)
コード例 #3
0
ファイル: test_properties.py プロジェクト: Coffelius/kivy
    def test_propertynone(self):
        from kivy.properties import NumericProperty

        a = NumericProperty(0, allownone=True)
        a.link(wid, 'a')
        a.link_deps(wid, 'a')
        self.assertEqual(a.get(wid), 0)
        try:
            a.set(wid, None)
            self.assertEqual(a.get(wid), None)
        except ValueError, e:
            pass
コード例 #4
0
ファイル: test_properties.py プロジェクト: 5y/kivy
    def test_reference_child_update(self):
        from kivy.properties import NumericProperty, ReferenceListProperty

        x = NumericProperty(0)
        x.link(wid, 'x')
        x.link_deps(wid, 'x')
        y = NumericProperty(0)
        y.link(wid, 'y')
        y.link_deps(wid, 'y')
        pos = ReferenceListProperty(x, y)
        pos.link(wid, 'pos')
        pos.link_deps(wid, 'pos')

        pos.get(wid)[0] = 10
        self.assertEqual(pos.get(wid), [10, 0])

        pos.get(wid)[:] = (20, 30)
        self.assertEqual(pos.get(wid), [20, 30])
コード例 #5
0
ファイル: knob.py プロジェクト: suelliton/DrumdiyController
class Knob(Widget):
    """Class for creating a Knob widget."""

    min = NumericProperty(0)
    '''Minimum value for value :attr:`value`.
    :attr:`min` is a :class:`~kivy.properties.NumericProperty` and defaults
    to 0.
    '''

    max = NumericProperty(100)
    '''Maximum value for value :attr:`value`.
    :attr:`max` is a :class:`~kivy.properties.NumericProperty` and defaults
    to 100.
    '''

    range = ReferenceListProperty(min, max)
    ''' Range of the values for Knob.
    :attr:`range` is a :class:`~kivy.properties.ReferenceListProperty` of
    (:attr:`min`, :attr:`max`).
    '''

    value = NumericProperty(0)
    '''Current value of the knob. Set :attr:`value` when creating a knob to
    set its initial position. An internal :attr:`_angle` is calculated to set
    the position of the knob.
    :attr:`value` is a :class:`~kivy.properties.NumericProperty` and defaults
    to 0.
    '''

    step = BoundedNumericProperty(1, min=0)
    '''Step interval of knob to go from min to max. An internal
    :attr:`_angle_step` is calculated to set knob step in degrees.
    :attr:`step` is a :class:`~kivy.properties.BoundedNumericProperty`
    and defaults to 1 (min=0).
    '''

    curve = BoundedNumericProperty(1, min=1)
    '''This parameter determines the shape of the map function. It represent the
    reciprocal of a power function's exponent used to map the input value.
    So, for higher values of curve the contol is more reactive, and conversely.
    '''

    knobimg_source = StringProperty("")
    '''Path of texture image that visually represents the knob. Use PNG for
    transparency support. The texture is rendered on a centered rectangle of
    size = :attr:`size` * :attr:`knobimg_size`.
    :attr:`knobimg_source` is a :class:`~kivy.properties.StringProperty`
    and defaults to empty string.
    '''

    knobimg_color = ListProperty([1, 1, 1, 1])
    '''Color to apply to :attr:`knobimg_source` texture when loaded.
    :attr:`knobimg_color` is a :class:`~kivy.properties.ListProperty`
    and defaults to [1,1,1,1].
    '''

    knobimg_size = BoundedNumericProperty(1.0, max=1.0, min=0.1)
    ''' Internal proportional size of rectangle that holds
    :attr:`knobimg_source` texture.
    :attr:`knobimg_size` is a :class:`~kivy.properties.BoundedNumericProperty`
    and defaults to 0.9.
    '''

    show_marker = BooleanProperty(True)
    ''' Shows/hides marker surrounding knob. use :attr:`knob_size` < 1.0 to
    leave space to marker.
    :attr:`show_marker` is a :class:`~kivy.properties.BooleanProperty`
    and defaults to True.
    '''

    marker_img = StringProperty("")
    '''Path of texture image that visually represents the knob marker. The
    marker is rendered in a centered Ellipse (Circle) with the same size of
    the widget and goes from angle_start=:attr:`marker_startangle` to
    angle_end=:attr:`_angle`.
    :attr:`marker_img` is a :class:`~kivy.properties.StringProperty` and
    defaults to "".
    '''

    marker_color = ListProperty([1, 1, 1, 1])
    '''Color to apply to :attr:`marker_img` texture when loaded.
    :attr:`marker_color` is a :class:`~kivy.properties.ListProperty`
    and defaults to [1,1,1,1].
    '''

    knobimg_bgcolor = ListProperty([0, 0, 0, 1])
    ''' Background color behind :attr:`knobimg_source` texture.
    :attr:`value` is a :class:`~kivy.properties.ListProperty` and defaults
    to [0,0,0,1].
    '''

    markeroff_img = StringProperty("")
    '''Path of texture image that visually represents the knob marker where
    it's off, that is, parts of the marker that haven't been reached yet by
    the knob (:attr:`value`).
    :attr:`markeroff_img` is a :class:`~kivy.properties.StringProperty`
    and defaults to "".
    '''

    markeroff_color = ListProperty([0, 0, 0, 0])
    '''Color applied to :attr:`markeroff_img` int the Canvas.
    :attr:`markeroff_color` is a :class:`~kivy.properties.ListProperty`
    and defaults to [0,0,0,0].
    '''

    marker_startangle = NumericProperty(0)
    '''Starting angle of Ellipse where :attr:`marker_img` is rendered.
    :attr:`value` is a :class:`~kivy.properties.NumericProperty` and defaults
    to 0.
    '''

    marker_ahead = NumericProperty(0)
    ''' Adds degrees to angle_end of marker (except when :attr:`value` == 0).
    :attr:`marker_ahead` is a :class:`~kivy.properties.NumericProperty`
    and defaults to 0.
    '''

    _angle = NumericProperty(0)  # Internal angle calculated from value.
    _angle_step = NumericProperty(
        0)  # Internal angle_step calculated from step.

    def __init__(self, *args, **kwargs):
        super(Knob, self).__init__(*args, **kwargs)
        self.bind(show_marker=self._show_marker)
        self.bind(value=self._value)

    def _value(self, instance, value):
        self._angle = pow(
            (value - self.min) / (self.max - self.min), 1. / self.curve) * 360.
        self.on_knob(value)

    def _show_marker(self, instance, flag):
        # "show/hide" marker.
        if flag:
            self.knobimg_bgcolor[3] = 1
            self.marker_color[3] = 1
            self.markeroff_color[3] = 1
        else:
            self.knobimg_bgcolor[3] = 0
            self.marker_color[3] = 0
            self.markeroff_color[3] = 0

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            self.update_angle(touch)

    def on_touch_move(self, touch):
        if self.collide_point(*touch.pos):
            self.update_angle(touch)

    def update_angle(self, touch):
        posx, posy = touch.pos
        cx, cy = self.center
        rx, ry = posx - cx, posy - cy

        if ry >= 0:  # Quadrants are clockwise.
            quadrant = 1 if rx >= 0 else 4
        else:
            quadrant = 3 if rx <= 0 else 2

        try:
            angle = math.atan(rx / ry) * (180. / math.pi)
            if quadrant == 2 or quadrant == 3:
                angle = 180 + angle
            elif quadrant == 4:
                angle = 360 + angle

        except:  # atan not def for angle 90 and 270
            angle = 90 if quadrant <= 2 else 270

        self._angle_step = (self.step * 360) / (self.max - self.min)
        self._angle = self._angle_step
        while self._angle < angle:
            self._angle = self._angle + self._angle_step

        relativeValue = pow((angle / 360.), 1. / self.curve)
        self.value = (relativeValue * (self.max - self.min)) + self.min

    #TO OVERRIDE
    def on_knob(self, value):
        pass
コード例 #6
0
ファイル: test_properties.py プロジェクト: AWolf81/kivy
    def test_numeric_string_with_units_check(self):
        from kivy.properties import NumericProperty

        a = NumericProperty()
        a.link(wid, 'a')
        a.link_deps(wid, 'a')
        self.assertEqual(a.get(wid), 0)

        a.set(wid, '55dp')
        self.assertEqual(a.get(wid), 55)
        self.assertEqual(a.get_format(wid), 'dp')

        a.set(wid, u'55dp')
        self.assertEqual(a.get(wid), 55)
        self.assertEqual(a.get_format(wid), 'dp')

        a.set(wid, '99in')
        self.assertEqual(a.get(wid), 9504.0)
        self.assertEqual(a.get_format(wid), 'in')

        a.set(wid, u'99in')
        self.assertEqual(a.get(wid), 9504.0)
        self.assertEqual(a.get_format(wid), 'in')
コード例 #7
0
class AccordionItem(FloatLayout):
    '''AccordionItem class that must be used in conjunction with the
    :class:`Accordion` class. See the module documentation for more
    information.
    '''

    title = StringProperty('')
    '''Title string of the item. The title might be used in conjunction 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
    title text. See title_template and the example below.

    :attr:`title` is a :class:`~kivy.properties.StringProperty` and defaults
    to ''.
    '''

    title_template = StringProperty('AccordionItemTitle')
    '''Template to use for creating the title part of the accordion item. The
    default template is a simple Label, not customizable (except the text) that
    supports vertical and horizontal orientation and different backgrounds for
    collapse and selected mode.

    It's better to create and use your own template if the default template
    does not suffice.

    :attr:`title` is a :class:`~kivy.properties.StringProperty` and defaults to
    'AccordionItemTitle'. The current default template lives in the
    `kivy/data/style.kv` file.

    Here is the code if you want to build your own template::

        [AccordionItemTitle@Label]:
            text: ctx.title
            canvas.before:
                Color:
                    rgb: 1, 1, 1
                BorderImage:
                    source:
                        ctx.item.background_normal \
                        if ctx.item.collapse \
                        else ctx.item.background_selected
                    pos: self.pos
                    size: self.size
                PushMatrix
                Translate:
                    xy: self.center_x, self.center_y
                Rotate:
                    angle: 90 if ctx.item.orientation == 'horizontal' else 0
                    axis: 0, 0, 1
                Translate:
                    xy: -self.center_x, -self.center_y
            canvas.after:
                PopMatrix


    '''

    title_args = DictProperty({})
    '''Default arguments that will be passed to the
    :meth:`kivy.lang.Builder.template` method.

    :attr:`title_args` is a :class:`~kivy.properties.DictProperty` and defaults
    to {}.
    '''

    collapse = BooleanProperty(True)
    '''Boolean to indicate if the current item is collapsed or not.

    :attr:`collapse` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to True.
    '''

    collapse_alpha = NumericProperty(1.)
    '''Value between 0 and 1 to indicate how much the item is collapsed (1) or
    whether it is selected (0). It's mostly used for animation.

    :attr:`collapse_alpha` is a :class:`~kivy.properties.NumericProperty` and
    defaults to 1.
    '''

    accordion = ObjectProperty(None)
    '''Instance of the :class:`Accordion` that the item belongs to.

    :attr:`accordion` is an :class:`~kivy.properties.ObjectProperty` and
    defaults to None.
    '''

    background_normal = StringProperty(
        'atlas://data/images/defaulttheme/button')
    '''Background image of the accordion item used for the default graphical
    representation when the item is collapsed.

    :attr:`background_normal` is a :class:`~kivy.properties.StringProperty` and
    defaults to 'atlas://data/images/defaulttheme/button'.
    '''

    background_disabled_normal = StringProperty(
        'atlas://data/images/defaulttheme/button_disabled')
    '''Background image of the accordion item used for the default graphical
    representation when the item is collapsed and disabled.

    .. versionadded:: 1.8.0

    :attr:`background__disabled_normal` is a
    :class:`~kivy.properties.StringProperty` and defaults to
    'atlas://data/images/defaulttheme/button_disabled'.
    '''

    background_selected = StringProperty(
        'atlas://data/images/defaulttheme/button_pressed')
    '''Background image of the accordion item used for the default graphical
    representation when the item is selected (not collapsed).

    :attr:`background_normal` is a :class:`~kivy.properties.StringProperty` and
    defaults to 'atlas://data/images/defaulttheme/button_pressed'.
    '''

    background_disabled_selected = StringProperty(
        'atlas://data/images/defaulttheme/button_disabled_pressed')
    '''Background image of the accordion item used for the default graphical
    representation when the item is selected (not collapsed) and disabled.

    .. versionadded:: 1.8.0

    :attr:`background_disabled_selected` is a
    :class:`~kivy.properties.StringProperty` and defaults to
    'atlas://data/images/defaulttheme/button_disabled_pressed'.
    '''

    orientation = OptionProperty('vertical', options=(
        'horizontal', 'vertical'))
    '''Link to the :attr:`Accordion.orientation` property.
    '''

    min_space = NumericProperty('44dp')
    '''Link to the :attr:`Accordion.min_space` property.
    '''

    content_size = ListProperty([100, 100])
    '''(internal) Set by the :class:`Accordion` to the size allocated for the
    content.
    '''

    container = ObjectProperty(None)
    '''(internal) Property that will be set to the container of children inside
    the AccordionItem representation.
    '''

    container_title = ObjectProperty(None)
    '''(internal) Property that will be set to the container of title inside
    the AccordionItem representation.
    '''

    def __init__(self, **kwargs):
        self._trigger_title = Clock.create_trigger(self._update_title, -1)
        self._anim_collapse = None
        super(AccordionItem, self).__init__(**kwargs)
        trigger_title = self._trigger_title
        fbind = self.fbind
        fbind('title', trigger_title)
        fbind('title_template', trigger_title)
        fbind('title_args', trigger_title)
        trigger_title()

    def add_widget(self, widget):
        if self.container is None:
            return super(AccordionItem, self).add_widget(widget)
        return self.container.add_widget(widget)

    def remove_widget(self, widget):
        if self.container:
            self.container.remove_widget(widget)
        super(AccordionItem, self).remove_widget(widget)

    def on_collapse(self, instance, value):
        accordion = self.accordion
        if accordion is None:
            return
        if not value:
            self.accordion.select(self)
        collapse_alpha = float(value)
        if self._anim_collapse:
            self._anim_collapse.stop(self)
            self._anim_collapse = None
        if self.collapse_alpha != collapse_alpha:
            self._anim_collapse = Animation(
                collapse_alpha=collapse_alpha,
                t=accordion.anim_func,
                d=accordion.anim_duration)
            self._anim_collapse.start(self)

    def on_collapse_alpha(self, instance, value):
        self.accordion._trigger_layout()

    def on_touch_down(self, touch):
        if not self.collide_point(*touch.pos):
            return
        if self.disabled:
            return True
        if self.collapse:
            self.collapse = False
            return True
        else:
            return super(AccordionItem, self).on_touch_down(touch)

    def _update_title(self, dt):
        if not self.container_title:
            self._trigger_title()
            return
        c = self.container_title
        c.clear_widgets()
        instance = Builder.template(self.title_template,
                                    title=self.title,
                                    item=self,
                                    **self.title_args)
        c.add_widget(instance)
コード例 #8
0
ファイル: graph_drives.py プロジェクト: yisea123/YaskawaCoE
class GraphRotatedLabel(Label):
    angle = NumericProperty(0)
コード例 #9
0
ファイル: graph_drives.py プロジェクト: yisea123/YaskawaCoE
class Plot(EventDispatcher):
    '''Plot class, see module documentation for more information.

    :Events:
        `on_clear_plot`
            Fired before a plot updates the display and lets the fbo know that
            it should clear the old drawings.

    ..versionadded:: 0.4
    '''

    __events__ = ('on_clear_plot', )

    # most recent values of the params used to draw the plot
    params = DictProperty({
        'xlog': False,
        'xmin': 0,
        'xmax': 100,
        'ylog': False,
        'ymin': 0,
        'ymax': 100,
        'size': (0, 0, 0, 0)
    })

    color = ListProperty([1, 1, 1, 1])
    '''Color of the plot.
    '''

    points = ListProperty([])
    '''List of (x, y) points to be displayed in the plot.

    The elements of points are 2-tuples, (x, y). The points are displayed
    based on the mode setting.

    :data:`points` is a :class:`~kivy.properties.ListProperty`, defaults to
    [].
    '''

    x_axis = NumericProperty(0)
    '''Index of the X axis to use, defaults to 0
    '''

    y_axis = NumericProperty(0)
    '''Index of the Y axis to use, defaults to 0
    '''
    def __init__(self, **kwargs):
        super(Plot, self).__init__(**kwargs)
        self.ask_draw = Clock.create_trigger(self.draw)
        self.bind(params=self.ask_draw, points=self.ask_draw)
        self._drawings = self.create_drawings()

    def funcx(self):
        """Return a function that convert or not the X value according to plot
        prameters"""
        return log10 if self.params["xlog"] else lambda x: x

    def funcy(self):
        """Return a function that convert or not the Y value according to plot
        prameters"""
        return log10 if self.params["ylog"] else lambda y: y

    def x_px(self):
        """Return a function that convert the X value of the graph to the
        pixel coordinate on the plot, according to the plot settings and axis
        settings
        """
        funcx = self.funcx()
        params = self.params
        size = params["size"]
        xmin = funcx(params["xmin"])
        xmax = funcx(params["xmax"])
        ratiox = (size[2] - size[0]) / float(xmax - xmin)
        return lambda x: (funcx(x) - xmin) * ratiox + size[0]

    def y_px(self):
        """Return a function that convert the Y value of the graph to the
        pixel coordinate on the plot, according to the plot settings and axis
        settings
        """
        funcy = self.funcy()
        params = self.params
        size = params["size"]
        ymin = funcy(params["ymin"])
        ymax = funcy(params["ymax"])
        ratioy = (size[3] - size[1]) / float(ymax - ymin)
        return lambda y: (funcy(y) - ymin) * ratioy + size[1]

    def unproject(self, x, y):
        """Return a function that unproject a pixel to a X/Y value on the plot
        (works only for linear, not log yet)
        """
        params = self.params
        size = params["size"]
        xmin = params["xmin"]
        xmax = params["xmax"]
        ymin = params["ymin"]
        ymax = params["ymax"]
        ratiox = (size[2] - size[0]) / float(xmax - xmin)
        ratioy = (size[3] - size[1]) / float(ymax - ymin)
        x0 = (x - size[0]) / ratiox + xmin
        y0 = (y - size[1]) / ratioy + ymin
        return x0, y0

    def get_px_bounds(self):
        """Returns a dict containing the pixels bounds from the plot parameters
        """
        params = self.params
        x_px = self.x_px()
        y_px = self.y_px()
        return {
            "xmin": x_px(params["xmin"]),
            "xmax": x_px(params["xmax"]),
            "ymin": y_px(params["ymin"]),
            "ymax": y_px(params["ymax"]),
        }

    def update(self, xlog, xmin, xmax, ylog, ymin, ymax, size):
        '''Called by graph whenever any of the parameters
        change. The plot should be recalculated then.
        log, min, max indicate the axis settings.
        size a 4-tuple describing the bounding box in which we can draw
        graphs, it's (x0, y0, x1, y1), which correspond with the bottom left
        and top right corner locations, respectively.
        '''
        self.params.update({
            'xlog': xlog,
            'xmin': xmin,
            'xmax': xmax,
            'ylog': ylog,
            'ymin': ymin,
            'ymax': ymax,
            'size': size
        })

    def get_group(self):
        '''returns a string which is unique and is the group name given to all
        the instructions returned by _get_drawings. Graph uses this to remove
        these instructions when needed.
        '''
        return ''

    def get_drawings(self):
        '''returns a list of canvas instructions that will be added to the
        graph's canvas.
        '''
        if isinstance(self._drawings, (tuple, list)):
            return self._drawings
        return []

    def create_drawings(self):
        '''called once to create all the canvas instructions needed for the
        plot
        '''
        pass

    def draw(self, *largs):
        '''draw the plot according to the params. It dispatches on_clear_plot
        so derived classes should call super before updating.
        '''
        self.dispatch('on_clear_plot')

    def iterate_points(self):
        '''Iterate on all the points adjusted to the graph settings
        '''
        x_px = self.x_px()
        y_px = self.y_px()
        for x, y in self.points:
            yield x_px(x), y_px(y)

    def on_clear_plot(self, *largs):
        pass

    # compatibility layer
    _update = update
    _get_drawings = get_drawings
    _params = params
コード例 #10
0
ファイル: race.py プロジェクト: prospero-apps/python
class SlugStats(BoxLayout):
    name = StringProperty('')
    wins = NumericProperty(0)
    win_percent = NumericProperty(0)
コード例 #11
0
ファイル: race.py プロジェクト: prospero-apps/python
class SlugInfo(BoxLayout):
    y_position = NumericProperty(0)
    name = StringProperty('')
    wins = NumericProperty(0)
コード例 #12
0
class MDSwiper(ScrollView, EventDispatcher):
    items_spacing = NumericProperty("20dp")
    """
    The space between each :class:`MDSwiperItem`.

    :attr:`items_spacing` is an :class:`~kivy.properties.NumericProperty`
    and defaults to `20dp`.
    """

    transition_duration = NumericProperty(0.2)
    """
    Duration of switching between :class:`MDSwiperItem`.

    :attr:`transition_duration` is an :class:`~kivy.properties.NumericProperty`
    and defaults to `0.2`.
    """

    size_duration = NumericProperty(0.2)
    """
    Duration of changing the size of :class:`MDSwiperItem`.

    :attr:`transition_duration` is an :class:`~kivy.properties.NumericProperty`
    and defaults to `0.2`.
    """

    size_transition = StringProperty("out_quad")
    """
    The type of animation used for changing the size of :class:`MDSwiperItem`.

    :attr:`size_transition` is an :class:`~kivy.properties.StringProperty`
    and defaults to `out_quad`.
    """

    swipe_transition = StringProperty("out_quad")
    """
    The type of animation used for swiping.

    :attr:`swipe_transition` is an :class:`~kivy.properties.StringProperty`
    and defaults to `out_quad`.
    """

    swipe_distance = NumericProperty("70dp")
    """
    Distance to move before swiping the :class:`MDSwiperItem`.

    :attr:`swipe_distance` is an :class:`~kivy.properties.NumericProperty`
    and defaults to `70dp`.
    """

    width_mult = NumericProperty(3)
    """
    This number is multiplied by :attr:`items_spacing` x2 and
    then subtracted from the width of window to specify the width of
    :class:`MDSwiperItem`. So by decreasing the :attr:`width_mult` the width
    of :class:`MDSwiperItem` increases and vice versa.

    :attr:`width_mult` is an :class:`~kivy.properties.NumericProperty`
    and defaults to `3`.
    """

    swipe_on_scroll = BooleanProperty(True)
    """
    Wheter to swipe on mouse wheel scrolling or not.

    :attr:`swipe_on_scroll` is an :class:`~kivy.properties.BooleanProperty`
    and defaults to `True`.
    """

    _selected = 0
    _start_touch_x = None

    __events__ = (
        "on_swipe",
        "on_pre_swipe",
        "on_overswipe_right",
        "on_overswipe_left",
        "on_swipe_left",
        "on_swipe_right",
    )

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.register_event_type("on_swipe")
        self.register_event_type("on_pre_swipe")
        self.register_event_type("on_overswipe_right")
        self.register_event_type("on_overswipe_left")
        self.register_event_type("on_swipe_left")
        self.register_event_type("on_swipe_right")

        self.effect_cls = _ScrollViewHardStop

    def add_widget(self, widget, index=0):
        if issubclass(widget.__class__, MDSwiperItem):
            widget._root = self
            items_box = _ItemsBox(_root=self)
            items_box.add_widget(widget)
            self.ids.anchor_scroll.add_widget(items_box)
            return
        else:
            return super().add_widget(widget, index=index)

    def remove_widget(self, widget):
        if not issubclass(widget.__class__, MDSwiperItem):
            return

        for item_box in self.ids.anchor_scroll.children:
            if widget in item_box.children:
                return self.ids.anchor_scroll.remove_widget(item_box)

    def set_current(self, index):
        """Switch to given :class:`MDSwiperItem` index."""

        self._selected = index
        self.dispatch("on_pre_swipe")
        self._reset_size()
        self.dispatch("on_swipe")

    def get_current_index(self):
        """Returns the current :class:`MDSwiperItem` index."""

        return self._selected

    def get_current_item(self):
        """Returns the current :class:`MDSwiperItem` instance."""

        return list(reversed(
            self.ids.anchor_scroll.children))[self._selected].children[0]

    def get_items(self):
        """Returns the list of :class:`MDSwiperItem` children.

        .. note::

            Use `get_items()` to get the list of children instead of
            `MDSwiper.children`.

        """

        children = list(reversed(self.ids.anchor_scroll.children))
        items = [item.children[0] for item in children]
        return items

    def _reset_size(self, *args):
        children = list(reversed(self.ids.anchor_scroll.children))
        if not children:
            return
        child = children[self._selected]
        total_width = self.ids.anchor_scroll.width - Window.width
        view_x = child.x - self.items_spacing * self.width_mult
        anim = Animation(
            scroll_x=view_x / total_width,
            d=self.transition_duration,
            t=self.swipe_transition,
        )
        anim.start(self)

        for widget in children:
            widget.children[0]._dismiss_size()
            widget.children[0]._selected = False
        child.children[0]._selected_size()
        child.children[0]._selected = True

    def on_swipe(self):
        pass

    def on_pre_swipe(self):
        pass

    def on_overswipe_right(self):
        pass

    def on_overswipe_left(self):
        pass

    def on_swipe_left(self):
        pass

    def on_swipe_right(self):
        pass

    def swipe_left(self):
        previous_index = self._selected - 1
        if previous_index == -1:
            self.set_current(0)
            self.dispatch("on_overswipe_left")
        else:
            self.set_current(previous_index)
            self.dispatch("on_swipe_left")

    def swipe_right(self):
        next_index = self._selected + 1
        last_index = len(self.ids.anchor_scroll.children) - 1
        if next_index == last_index + 1:
            self.set_current(last_index)
            self.dispatch("on_overswipe_right")
        else:
            self.set_current(next_index)
            self.dispatch("on_swipe_right")

    def on_scroll_start(self, touch, check_children=True):

        if platform in ["ios", "android"]:
            return super().on_scroll_start(touch)

        # on touch pad events
        if touch.button == "scrollright":
            self.swipe_left()
        elif touch.button == "scrollleft":
            self.swipe_right()
        return super().on_scroll_start(touch)

    def on_touch_down(self, touch):
        super().on_touch_down(touch)

        if not self.collide_point(touch.pos[0], touch.pos[1]):
            return

        if platform not in ["ios", "android"] and self.swipe_on_scroll:
            if touch.button == "scrolldown":
                self.swipe_right()
            elif touch.button == "scrollup":
                self.swipe_left()
            else:
                self._start_touch_x = touch.pos[0]
        else:
            self._start_touch_x = touch.pos[0]

    def on_touch_up(self, touch):
        super().on_touch_up(touch)
        if not self._start_touch_x:
            return

        if self._start_touch_x:
            touch_x_diff = abs(self._start_touch_x - touch.pos[0])
        else:
            return

        if touch_x_diff <= self.swipe_distance:
            if touch_x_diff == 0:
                return
            self._reset_size()
            return

        # swipe to left
        if self._start_touch_x < touch.pos[0]:
            self.swipe_left()
        # swipe to right
        else:
            self.swipe_right()

        self._start_touch_x = None
        return
コード例 #13
0
ファイル: utils.py プロジェクト: OMR-Research/MUSCIMarker
class ImageToModelScaler(Widget):
    """Use this class when you have an image inside a ScatterLayout
    and you need to convert coordinates from the Image widget to coordinates
    in the underlying image.

    If your widget coords are represented as (X, Y, height, width),
    use the cropobject_widget2model() method. If your widget coords
    are (top, left, bottom, right), use bbox_widget2model(). Note that
    in the second case, we expect top to be the widget-world top, so it
    will have a *larger* value than bottom. This second method can be used
    directly with the ('top', 'left', 'bottom', 'right') selection dictionary
    recorded by a BoundingBoxTracer.

    Note: when we say 'top', 'bottom', 'left' or 'right' in this context,
    we mean it in a WYSIWYG manner: the coordinate corresponding to the top
    boundary of the object you are seeing on the screen.

    If you need to map individual (X, Y) points: use point_widget2model
    and point_model2widget.

    """
    widget_height = NumericProperty(1.0)
    widget_width = NumericProperty(1.0)

    model_height = NumericProperty(1.0)
    model_width = NumericProperty(1.0)

    def __init__(self, image_widget, image_model, **kwargs):
        """Initialize the widget.

        :param image_widget: The Image widget. Expects coordinates to be
            bottom to top, left to right (counted from the bottom left corner).

        :param image_model: A numpy array of the actual image. Assumes
            shape[0] is height, shape[1] is width.
        """
        super(ImageToModelScaler, self).__init__(**kwargs)
        # logging.info('Scaler: image widget: {0}'.format(image_widget))
        # logging.info('Scaler: image widget parent: {0}'.format(image_widget.parent))
        # logging.info('Scaler: image widget pparent: {0}'.format(image_widget.parent.parent))
        self.reset(image_widget, image_model)

    def reset(self, image_widget, image_model):
        logging.info('Scaler: RESET')
        # Bind widget shape changes to our properties.
        image_widget.bind(height=self.set_widget_height)
        image_widget.bind(width=self.set_widget_width)
        self.widget_height = image_widget.height
        self.widget_width = image_widget.width
        logging.info('Scaler: Widget image shape: {0}'.format((self.widget_height,
                                                       self.widget_width)))

        model_shape = image_model.shape
        self.model_height = model_shape[0]
        self.model_width = model_shape[1]
        logging.info('Scaler: Model image shape: {0}'.format(model_shape))
        logging.info('Scaler: m2w ratios: {0}'.format((self.m2w_ratio_height,
                                               self.m2w_ratio_width)))
        logging.info('Scaler: w2m ratios: {0}'.format((self.w2m_ratio_height,
                                               self.w2m_ratio_width)))

    def cropobject_widget2model(self, wX, wY, wHeight, wWidth):
        raise NotImplementedError()

    def cropobject_model2widget(self, mX, wY, mHeight, mWidth):
        raise NotImplementedError()

    def bbox_widget2model(self, wTop, wLeft, wBottom, wRight):
        mTop = (self.widget_height - wTop) * self.w2m_ratio_height
        mBottom = (self.widget_height - wBottom) * self.w2m_ratio_height
        mLeft = wLeft * self.w2m_ratio_width
        mRight = wRight * self.w2m_ratio_width
        logging.info('Scaler: From widget: {0} to model: {1}. w2m ratios: {2}'
                     ''.format((wTop, wLeft, wBottom, wRight),
                               (mTop, mLeft, mBottom, mRight),
                               (self.w2m_ratio_height, self.w2m_ratio_width)))
        return mTop, mLeft, mBottom, mRight

    def bbox_model2widget(self, mTop, mLeft, mBottom, mRight):
        wTop = self.widget_height - (mTop * self.m2w_ratio_height)
        wBottom = self.widget_height - (mBottom * self.m2w_ratio_height)
        wLeft = mLeft * self.m2w_ratio_width
        wRight = mRight * self.m2w_ratio_width
        return wTop, wLeft, wBottom, wRight

    def point_widget2model(self, wX, wY):
        """Maps a point from the widget (kivy) space to the model (numpy) space.

        :param wX: horizontal coordinate

        :param wY: vertical coordinate

        :returns: A tuple (mX, mY), where mX is the model *vertical* coordinate
            (row) and mY is the model *horizontal* coordinate (column).
        """
        mX = (self.widget_height - wY) * self.w2m_ratio_height
        mY = wX * self.w2m_ratio_width
        return mX, mY

    def point_model2widget(self, mX, mY):
        """Maps a point from the widget (kivy) space to the model (numpy) space.

        :param mX: horizontal coordinate

        :param mY: vertical coordinate

        :returns: A tuple (wX, wY), where wX is the widget *horizontal* coordinate
            (column) and wY is the model *vertical* coordinate (row), measured
            from the *bottom*.
        """
        raise NotImplementedError()

    ###################################
    # Listening to widget size changes.

    def set_widget_height(self, instance, pos):
        logging.info('Scaler: widget height change triggered, pos={0}'.format(pos))
        self.widget_height = pos

    def set_widget_width(self, instance, pos):
        logging.info('Scaler: widget width change triggered, pos={0}'.format(pos))
        self.widget_width = pos

    ####################################
    # Scaling ratios.
    # "m2w" is "multiply by this ratio when converting from Model to Widget".
    # "w2m" is "multiply by this ratio when converting from Widget to Model".
    @property
    def m2w_ratio_height(self):
        return self.widget_height * 1.0 / self.model_height

    @property
    def m2w_ratio_width(self):
        return self.widget_width * 1.0 / self.model_width

    @property
    def w2m_ratio_height(self):
        return self.model_height * 1.0 / self.widget_height

    @property
    def w2m_ratio_width(self):
        return self.model_width * 1.0 / self.widget_width
コード例 #14
0
ファイル: canvas3d.py プロジェクト: Cophy08/kivy3dgui
class Canvas3D(FloatLayout):
    adding_queue = []
    '''adding_queue_doc
    '''

    translate = ListProperty([0.0, 0.0, 0.0])
    ''' Translate all children widgets around the value
    '''

    rotate = ListProperty([0.0, 0.0, 0.0, 0.0])
    ''' Rotate all children widgets around the value
    '''

    _translate = None
    ''' Shadow FBO translate value
    '''

    _translate_fbo = None
    ''' Shadow FBO translate value
    '''

    _translate_picking = None
    ''' Picking FBO translate value
    '''

    _translate_motion = None
    ''' Motion FBO translate value
    '''

    nodes = []
    ''' Nodes list
    '''

    shadow = True
    ''' Shadow state, at now always the shadows is enable
    '''

    picking = True
    ''' Allow picking. At now always the picking is enable
    '''

    fbo = None
    ''' Shadow FBO
    '''

    fbo_list = {}
    ''' List of elements attached to a Mesh
    '''

    shadow_threshold = 1.0
    ''' Shadow Distance
    '''

    _update_fbo = 0

    current_id = 0.01
    '''Mesh ID counter
    '''

    last_touch_pos = [-1, -1, -1, -1]
    '''last_touch_pos counter
    '''

    perspective_value = NumericProperty(35.)
    '''Perspective value
    '''
    def __init__(self, **kwargs):
        self.shadow = kwargs.get("shadow", False)
        global PICKING_BUFFER_SIZE
        PICKING_BUFFER_SIZE = kwargs.get("canvas_size", Window.size)
        self.shadow = True
        self.picking = True
        self.co = self.canvas
        self.canvas = RenderContext(compute_normal_mat=False)

        #self.canvas.shader.source = resource_find('./kivy3dgui/gles2.0/shaders/simple_no_light.glsl')
        self.canvas.shader.source = resource_find(
            './kivy3dgui/gles2.0/toonshader/toon.glsl')
        self.alpha = 0.0
        self._touches = []
        with self.canvas:
            self._translate = Translate(0, 0, 0)
            self._rotate = Rotate(0.0, 1.0, 0.0, 0.0)
            PushMatrix()
            self.cbs = Callback(self.setup_gl_context)

            if self.shadow:
                self.create_fbo()
            if self.picking:
                self.create_picking_fbo()
            self.create_motion_blur()

        with self.canvas.before:
            self.cbs = Callback(self.setup_gl_context)
            if self.shadow:
                BindTexture(texture=self.fbo.texture, index=1)
                BindTexture(texture=self.motion_blur_fbo.texture, index=5)

            PushMatrix()

            self.setup_scene()
            PopMatrix()
            PushMatrix()
            self.cc = Callback(self.check_context)
            PopMatrix()
            UpdateNormalMatrix()

        with self.canvas.after:
            self.cbr = Callback(self.reset_gl_context)
            PopMatrix()
            #Fixing Shadow and Picking
        self.shadow = True
        self.picking = True
        if self.shadow:
            self.init_fbo()
        if self.picking:
            self.init_picking()
        self.init_motion_blur()
        super(Canvas3D, self).__init__(**kwargs)
        Clock.schedule_interval(self.update_glsl, 1 / 60.)
        self._touches = {}

    def pitch(self, value, time):
        self.rotate = [value, 1.0, 0.0, 0.0]
        Animation.stop_all(self)
        Animation(rotate=[0.0, 1.0, 0.0, 0.0], duration=time).start(self)

    def walk(self, value, time):
        self.translate = [0.0, 0.0, value]
        Animation.stop_all(self)
        Animation(translate=(0.0, 0.0, 0.0), duration=time).start(self)

    def strafe(self, value, time):
        self.translate = [value, 0.0, 0.0]
        Animation.stop_all(self)
        Animation(translate=(0.0, 0.0, 0.0), duration=time).start(self)

    def up(self, value, time):
        self.translate = [0.0, value, 0.0]
        Animation.stop_all(self)
        Animation(translate=(0.0, 0.0, 0.0), duration=time).start(self)

    def on_translate(self, widget, value):
        self._translate.xyz = value[0:3]
        self._translate_picking.xyz = value[0:3]
        self._translate_motion.xyz = value[0:3]
        self._translate_fbo.xyz = value[0:3]

    def on_rotate(self, widget, value):
        self._rotate.set(*value)
        self._rotate_picking.set(*value)
        self._rotate_motion.set(*value)
        self._rotate_fbo.set(*value)

    def init_picking(self):
        with self.picking_fbo:
            self._translate_picking = Translate(0, 0, 0)
            self._rotate_picking = Rotate(0.0, 1.0, 0.0, 0.0)
            PushMatrix()
            self.setup_scene()
            self._picking_instruction = InstructionGroup()

        with self.picking_fbo.after:
            self.cb = Callback(self.reset_gl_context)
            PopMatrix()

        self._picking_instruction.add(Callback(self.setup_gl_context_picking))

    def add_widget(self, *largs):
        canvas = self.canvas
        self.canvas = self.fbo
        ret = super(Canvas3D, self).add_widget(*largs)
        self.canvas = canvas
        return ret

    def init_fbo(self):
        with self.fbo:
            self._translate_fbo = Translate(0, 0, 0)
            self._rotate_fbo = Rotate(0.0, 1.0, 0.0, 0.0)
            PushMatrix()
            #ClearBuffers(clear_depth=True)
            self.cb = Callback(self.setup_gl_context_shadow)
            PushMatrix()
            self.setup_scene()
            PopMatrix()
            self._instruction = InstructionGroup()

        with self.fbo.after:
            self.cb = Callback(self.reset_gl_context)
            PopMatrix()

        self._instruction.add(Callback(self.setup_gl_context_shadow))

    def create_picking_fbo(self):
        self.picking_fbo = Fbo(size=PICKING_BUFFER_SIZE,
                               with_depthbuffer=True,
                               compute_normal_mat=True,
                               clear_color=(0.0, 0.0, 0.0, 0.0))

        self.picking_fbo.shader.source = resource_find(
            './kivy3dgui/gles2.0/shaders/selection.glsl')

    def create_fbo(self):
        self.fbo = Fbo(size=PICKING_BUFFER_SIZE,
                       with_depthbuffer=True,
                       compute_normal_mat=True,
                       clear_color=(1.0, 1.0, 1.0, 0.0))

        self.fbo.shader.source = resource_find(
            './kivy3dgui/gles2.0/shaders/shadowpass.glsl')

    def create_motion_blur(self):
        self.motion_blur_fbo = Fbo(size=PICKING_BUFFER_SIZE,
                                   with_depthbuffer=True,
                                   compute_normal_mat=True,
                                   clear_color=(1.0, 1.0, 1.0, 0.0))

        self.motion_blur_fbo.shader.source = resource_find(
            './kivy3dgui/gles2.0/shaders/dop.glsl')

    def init_motion_blur(self):
        with self.motion_blur_fbo:
            self._translate_motion = Translate(0, 0, 0)
            self._rotate_motion = Rotate(0.0, 1.0, 0.0, 0.0)
            PushMatrix()
            self.cb = Callback(self.setup_gl_context_motion_blur)
            PushMatrix()
            self.setup_scene()
            PopMatrix()
            self._instruction_motion_fbo = InstructionGroup()

        with self.motion_blur_fbo.after:
            self.cb = Callback(self.reset_gl_context)
            PopMatrix()

        self._instruction_motion_fbo.add(
            Callback(self.setup_gl_context_motion_blur))

    def setup_gl_context(self, *args):
        glEnable(GL_BLEND)
        glEnable(GL_CULL_FACE)
        glCullFace(GL_BACK)
        glEnable(GL_DEPTH_TEST)

    def setup_gl_context_shadow(self, *args):
        self.fbo.clear_buffer()

    def setup_gl_context_motion_blur(self, *args):
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_CULL_FACE)
        glCullFace(GL_BACK)

        self.motion_blur_fbo.clear_buffer()

    def setup_gl_context_picking(self, *args):
        glEnable(GL_DEPTH_TEST)
        self.picking_fbo.clear_buffer()

    def check_context(self, *args):
        pass

    def add_node(self, node):
        node.motion_id = len(self.nodes)
        self.adding_queue.append(node)
        self.nodes.append(node)
        with self.canvas.before:
            PushMatrix()
            Translate(bind=self._translate)
            node.start()
            PopMatrix()

        if self.shadow:
            with self.fbo:
                PushMatrix()
                node.start()
                PopMatrix()

        if self.picking:
            with self.picking_fbo:
                PushMatrix()
                node.start()
                PopMatrix()

        with self.motion_blur_fbo:
            PushMatrix()
            node.start()
            PopMatrix()

        node.populate_fbo(node)

    def reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)
        glDisable(GL_CULL_FACE)

    def update_fbo(self, time):
        width = self.width if self.width > 1 else 100
        height = self.height if self.height > 1 else 100
        asp = (width / float(height))
        proj = Matrix().view_clip(-asp, asp, -1, 1, 1, 600, 1)
        proj = Matrix()
        proj.perspective(self.perspective_value, asp, 1, 1000)

        lightInvDir = (0.5, 2, 2)
        depthProjectionMatrix = Matrix().view_clip(
            -100 * self.shadow_threshold, 100 * self.shadow_threshold,
            -100 * self.shadow_threshold, 100 * self.shadow_threshold,
            -100 * self.shadow_threshold, 200 * self.shadow_threshold * 2, 0)
        depthViewMatrix = Matrix().look_at(-0.5, -50, -100, 0, 0, 0, 0, 1, 0)
        depthModelMatrix = Matrix().identity()
        depthMVP = depthProjectionMatrix.multiply(depthViewMatrix).multiply(
            depthModelMatrix)

        self.fbo['projection_mat'] = proj
        self.fbo['depthMVP'] = depthMVP
        self.fbo['diffuse_light'] = (0.0, 1.0, 0.0)
        self.fbo['ambient_light'] = (0.1, 0.1, 0.1)
        for m_pos in range(len(self.nodes)):
            motion_matrix = Matrix().view_clip(-asp, asp, -1, 1, 1, 600, 1)
            angle = self.nodes[m_pos].rotate[0] * 3.14 / 180
            pos = self.nodes[m_pos].get_pos()

            trans = self.nodes[m_pos].translate[:]

            result = [0, 0, 0]
            result[0] = 0.3 if trans[0] < pos[0] else -0.3
            result[1] = 0.3 if trans[1] < pos[1] else -0.3
            result[2] = 0.3 if trans[2] < pos[2] else -0.3

            motion_matrix = motion_matrix.translate(trans[0] + 0.1,
                                                    trans[1] + 0.1, trans[2])
            self.motion_blur_fbo['oldTransformation{0}'.format(
                str(m_pos))] = motion_matrix

        self.motion_blur_fbo['projection_mat'] = proj
        self.motion_blur_fbo['depthMVP'] = depthMVP

        if self.picking_fbo:
            self.picking_fbo['projection_mat'] = proj

        self.alpha += 10 * time
        self.fbo['cond'] = (0.0, 0.7)
        self.fbo['val_sin'] = (self.alpha, 0.0)
        #self.perspective_value += 0.04

    def update_glsl(self, *largs):
        width = self.width if self.width > 1 else 100
        height = self.height if self.height > 1 else 100
        asp = width / float(height)
        proj = Matrix().view_clip(-asp, asp, -1, 1, 1, 600, 1)
        proj = Matrix()
        proj.perspective(self.perspective_value, asp, 1, 1000)

        matrix_camera = Matrix().identity()
        matrix_camera.look_at(0, 100, 300, 100, 0, -100, 0, 1, 0)
        self.canvas['projection_mat'] = proj
        self.canvas['diffuse_light'] = (0.0, 1.0, 0.0)
        self.canvas['ambient_light'] = (0.1, 0.1, 0.1)
        if self.shadow:
            self.canvas['texture1'] = 1
            self.canvas["enabled_shadow"] = 1.0
        else:

            self.canvas["enabled_shadow"] = 0.0
            self.canvas["texture1"] = 0

        depthProjectionMatrix = Matrix().view_clip(
            -100 * self.shadow_threshold, 100 * self.shadow_threshold,
            -100 * self.shadow_threshold, 100 * self.shadow_threshold,
            -100 * self.shadow_threshold, 200 * self.shadow_threshold * 2, 0)
        depthViewMatrix = Matrix().look_at(-0.5, -50, -100, 0, 0, 0, 0, 1, 0)
        depthModelMatrix = Matrix().identity()
        depthMVP = depthProjectionMatrix.multiply(depthViewMatrix).multiply(
            depthModelMatrix)
        self.canvas['depthMVP'] = depthMVP
        self.canvas['cond'] = (0.0, 0.7)
        self.canvas['val_sin'] = (self.alpha, 0.0)

        if self.shadow:
            self.update_fbo(largs[0])
            #label.text = str(Clock.get_rfps())

    def on_size(self, instance, value):
        self._update_fbo = 0
        self.picking_fbo.size = PICKING_BUFFER_SIZE
        self.motion_blur_fbo.size = PICKING_BUFFER_SIZE

    def setup_scene(self):
        Color(1, 1, 1, 1)
        PushMatrix()
        Translate(0, 0, 0)
        UpdateNormalMatrix()
        PopMatrix()

    def define_rotate_angle(self, touch):
        x_angle = (touch.dx / self.width) * 360
        y_angle = -1 * (touch.dy / self.height) * 360
        return x_angle, y_angle

    def get_pixel_color(self, x, y):
        w = PICKING_BUFFER_SIZE[0]
        h = PICKING_BUFFER_SIZE[1]
        x = int(x)
        y = int(y)
        p = self.picking_fbo.pixels
        z = p[int(y * w * 4 + x * 4):int(y * w * 4 + x * 4 + 4)]
        try:
            z = [float(r) / 255.0 for i, r in enumerate(z)]
        except:
            z = [ord(r) / 255.0 for r in z]
        return z

    def get_fixed_points(self, x, y, move=False):
        _size = Window.size
        _size = EventLoop.window.system_size
        if move:
            _x = x / _size[0]
            _y = y / _size[1]
            return _x * PICKING_BUFFER_SIZE[0], _y * PICKING_BUFFER_SIZE[1]

        _x = x / _size[0]
        _y = y / _size[1]
        return _x * PICKING_BUFFER_SIZE[0], _y * PICKING_BUFFER_SIZE[1]

    def on_touch_down(self, touch):
        # transform the touch coordinate to local space
        x, y = self.get_fixed_points(touch.x, touch.y)
        pc = self.get_pixel_color(x, y)
        if pc == []:
            return False

        pc[1] = pc[1]
        pc[2] = pc[2]

        t_touch = copy.copy(touch)
        t_touch = touch
        t_touch.x = int(pc[1] * PICKING_BUFFER_SIZE[0])
        t_touch.y = int(pc[2] * PICKING_BUFFER_SIZE[1])
        self.last_touch_pos = [
            t_touch.x, t_touch.y,
            float(t_touch.x) / float(EventLoop.window.system_size[0]),
            float(t_touch.x) / float(EventLoop.window.system_size[1])
        ]
        t_touch.pos = (t_touch.x, t_touch.y)
        if pc[0] != 0:
            float_str = str(round(pc[0], 2))[0:4]
            if float(float_str) >= 0.50:
                float_str = str(round(float(float_str) - 0.50, 2))[0:4]
            if float_str in self.fbo_list:
                touch.ud["pick_value"] = float_str
                return self.fbo_list[float_str].on_touch_down(t_touch)
        return True

    def on_touch_move(self, touch):
        x, y = self.get_fixed_points(touch.x, touch.y)
        pc = self.get_pixel_color(x, y)
        if pc == []:
            return

        pc[1] = pc[1]
        pc[2] = pc[2]
        #fix
        if pc[0] != 0:
            float_str = str(round(pc[0], 2))[0:4]
            if float(float_str) >= 0.50:
                float_str = str(round(float(float_str) - 0.50, 2))[0:4]
            try:
                if touch.ud["pick_value"] != float_str:
                    return
            except:
                pass

        t_touch = copy.copy(touch)
        t_touch = touch
        t_touch.x = int(pc[1] * PICKING_BUFFER_SIZE[0])
        t_touch.y = int(pc[2] * PICKING_BUFFER_SIZE[1])

        if 'right' in t_touch.button:
            t_touch.pos = (t_touch.x, t_touch.y)
            return

        t_touch.sx = float(touch.x) / float(EventLoop.window.system_size[0])
        t_touch.sy = float(touch.y) / float(EventLoop.window.system_size[1])

        self.last_touch_pos = [t_touch.x, t_touch.y, t_touch.sx, t_touch.sy]
        if pc[0] != 0:
            float_str = str(round(pc[0], 2))[0:4]
            if float(float_str) >= 0.50:
                float_str = str(round(float(float_str) - 0.50, 2))[0:4]
            if float_str in self.fbo_list:
                ret = self.fbo_list[float_str].dispatch(
                    "on_touch_move", t_touch)
                return ret

        return True

    def on_touch_up(self, touch):
        x, y = self.get_fixed_points(touch.x, touch.y)
        pc = self.get_pixel_color(x, y)
        if pc == []:
            return
        pc[1] = pc[1]
        pc[2] = pc[2]
        t_touch = copy.copy(touch)
        t_touch = touch

        t_touch.x = self.last_touch_pos[0]
        t_touch.y = self.last_touch_pos[1]
        t_touch.sx = self.last_touch_pos[2]
        t_touch.sy = self.last_touch_pos[3]

        if pc[0] != 0:
            float_str = str(round(pc[0], 2))[0:4]
            if float(float_str) >= 0.50:
                float_str = str(round(float(float_str) - 0.50, 2))[0:4]
            if float_str in self.fbo_list:
                return self.fbo_list[float_str].on_touch_up(t_touch)
                pass

        return True
コード例 #15
0
ファイル: card.py プロジェクト: abang90/testapp
class MDCardSwipe(RelativeLayout):
    """
    :Events:
        :attr:`on_swipe_complete`
            Called when a swipe of card is completed.
    """

    open_progress = NumericProperty(0.0)
    """
    Percent of visible part of side panel. The percent is specified as a
    floating point number in the range 0-1. 0.0 if panel is closed and 1.0 if
    panel is opened.

    :attr:`open_progress` is a :class:`~kivy.properties.NumericProperty`
    and defaults to `0.0`.
    """

    opening_transition = StringProperty("out_cubic")
    """
    The name of the animation transition type to use when animating to
    the :attr:`state` `'opened'`.

    :attr:`opening_transition` is a :class:`~kivy.properties.StringProperty`
    and defaults to `'out_cubic'`.
    """

    closing_transition = StringProperty("out_sine")
    """
    The name of the animation transition type to use when animating to
    the :attr:`state` 'closed'.

    :attr:`closing_transition` is a :class:`~kivy.properties.StringProperty`
    and defaults to `'out_sine'`.
    """

    anchor = OptionProperty("left", options=("left", "right"))
    """
    Anchoring screen edge for card. Available options are: `'left'`, `'right'`.

    :attr:`anchor` is a :class:`~kivy.properties.OptionProperty`
    and defaults to `left`.
    """

    swipe_distance = NumericProperty(50)
    """
    The distance of the swipe with which the movement of navigation drawer
    begins.

    :attr:`swipe_distance` is a :class:`~kivy.properties.NumericProperty`
    and defaults to `10`.
    """

    opening_time = NumericProperty(0.2)
    """
    The time taken for the card to slide to the :attr:`state` `'open'`.

    :attr:`opening_time` is a :class:`~kivy.properties.NumericProperty`
    and defaults to `0.2`.
    """

    state = OptionProperty("closed", options=("closed", "opened"))
    """
    Detailed state. Sets before :attr:`state`. Bind to :attr:`state` instead
    of :attr:`status`. Available options are: `'closed'`,  `'opened'`.

    :attr:`status` is a :class:`~kivy.properties.OptionProperty`
    and defaults to `'closed'`.
    """

    max_swipe_x = NumericProperty(0.3)
    """
    If, after the events of :attr:`~on_touch_up` card position exceeds this
    value - will automatically execute the method :attr:`~open_card`,
    and if not - will automatically be :attr:`~close_card` method.

    :attr:`max_swipe_x` is a :class:`~kivy.properties.NumericProperty`
    and defaults to `0.3`.
    """

    max_opened_x = NumericProperty("100dp")
    """
    The value of the position the card shifts to when :attr:`~type_swipe` 
    s set to `'hand'`.

    :attr:`max_opened_x` is a :class:`~kivy.properties.NumericProperty`
    and defaults to `100dp`.
    """

    type_swipe = OptionProperty("hand", options=("auto", "hand"))
    """
    Type of card opening when swipe. Shift the card to the edge or to
    a set position :attr:`~max_opened_x`. Available options are:
    `'auto'`, `'hand'`.

    :attr:`type_swipe` is a :class:`~kivy.properties.OptionProperty`
    and defaults to `auto`.
    """

    _opens_process = False
    _to_closed = True

    def __init__(self, **kw):
        self.register_event_type("on_swipe_complete")
        super().__init__(**kw)

    def _on_swipe_complete(self, *args):
        self.dispatch("on_swipe_complete")

    def add_widget(self, widget, index=0, canvas=None):
        if isinstance(widget, (MDCardSwipeFrontBox, MDCardSwipeLayerBox)):
            return super().add_widget(widget)

    def on_swipe_complete(self, *args):
        """Called when a swipe of card is completed."""

    def on_anchor(self, instance, value):
        if value == "right":
            self.open_progress = 1.0
        else:
            self.open_progress = 0.0

    def on_open_progress(self, instance, value):
        if self.anchor == "left":
            self.children[0].x = self.width * value
        else:
            self.children[0].x = self.width * value - self.width

    def on_touch_move(self, touch):
        if self.collide_point(touch.x, touch.y):
            expr = (touch.x < self.swipe_distance if self.anchor == "left" else
                    touch.x > self.width - self.swipe_distance)
            if expr and not self._opens_process:
                self._opens_process = True
                self._to_closed = False
            if self._opens_process:
                self.open_progress = max(
                    min(self.open_progress + touch.dx / self.width, 2.5), 0)
        return super().on_touch_move(touch)

    def on_touch_up(self, touch):
        if self.collide_point(touch.x, touch.y):
            if not self._to_closed:
                self._opens_process = False
                self.complete_swipe()
        return super().on_touch_up(touch)

    def on_touch_down(self, touch):
        if self.collide_point(touch.x, touch.y):
            if self.state == "opened":
                self._to_closed = True
                self.close_card()
        return super().on_touch_down(touch)

    def complete_swipe(self):
        expr = (self.open_progress <= self.max_swipe_x if self.anchor == "left"
                else self.open_progress >= self.max_swipe_x)
        if expr:
            self.close_card()
        else:
            self.open_card()

    def open_card(self):
        if self.type_swipe == "hand":
            swipe_x = (self.max_opened_x
                       if self.anchor == "left" else -self.max_opened_x)
        else:
            swipe_x = self.width if self.anchor == "left" else 0
        anim = Animation(x=swipe_x,
                         t=self.opening_transition,
                         d=self.opening_time)
        anim.bind(on_complete=self._on_swipe_complete)
        anim.start(self.children[0])
        self.state = "opened"

    def close_card(self):
        anim = Animation(x=0, t=self.closing_transition, d=self.opening_time)
        anim.bind(on_complete=self._reset_open_progress)
        anim.start(self.children[0])
        self.state = "closed"

    def _reset_open_progress(self, *args):
        self.open_progress = 0.0 if self.anchor == "left" else 1.0
        self._to_closed = False
        self.dispatch("on_swipe_complete")
コード例 #16
0
class GridLayout(Layout):
    '''Grid layout class. See module documentation for more information.
    '''

    spacing = VariableListProperty([0, 0], length=2)
    '''Spacing between children: [spacing_horizontal, spacing_vertical].

    spacing also accepts a one argument form [spacing].

    :attr:`spacing` is a
    :class:`~kivy.properties.VariableListProperty` and defaults to [0, 0].
    '''

    padding = VariableListProperty([0, 0, 0, 0])
    '''Padding between the layout box and its children: [padding_left,
    padding_top, padding_right, padding_bottom].

    padding also accepts a two argument form [padding_horizontal,
    padding_vertical] and a one argument form [padding].

    .. versionchanged:: 1.7.0
        Replaced NumericProperty with VariableListProperty.

    :attr:`padding` is a :class:`~kivy.properties.VariableListProperty` and
    defaults to [0, 0, 0, 0].
    '''

    cols = BoundedNumericProperty(None, min=0, allownone=True)
    '''Number of columns in the grid.

    .. versionchanged:: 1.0.8
        Changed from a NumericProperty to BoundedNumericProperty. You can no
        longer set this to a negative value.

    :attr:`cols` is a :class:`~kivy.properties.NumericProperty` and defaults to
    None.
    '''

    rows = BoundedNumericProperty(None, min=0, allownone=True)
    '''Number of rows in the grid.

    .. versionchanged:: 1.0.8
        Changed from a NumericProperty to a BoundedNumericProperty. You can no
        longer set this to a negative value.

    :attr:`rows` is a :class:`~kivy.properties.NumericProperty` and defaults to
    None.
    '''

    col_default_width = NumericProperty(0)
    '''Default minimum size to use for a column.

    .. versionadded:: 1.0.7

    :attr:`col_default_width` is a :class:`~kivy.properties.NumericProperty`
    and defaults to 0.
    '''

    row_default_height = NumericProperty(0)
    '''Default minimum size to use for row.

    .. versionadded:: 1.0.7

    :attr:`row_default_height` is a :class:`~kivy.properties.NumericProperty`
    and defaults to 0.
    '''

    col_force_default = BooleanProperty(False)
    '''If True, ignore the width and size_hint_x of the child and use the
    default column width.

    .. versionadded:: 1.0.7

    :attr:`col_force_default` is a :class:`~kivy.properties.BooleanProperty`
    and defaults to False.
    '''

    row_force_default = BooleanProperty(False)
    '''If True, ignore the height and size_hint_y of the child and use the
    default row height.

    .. versionadded:: 1.0.7

    :attr:`row_force_default` is a :class:`~kivy.properties.BooleanProperty`
    and defaults to False.
    '''

    cols_minimum = DictProperty({})
    '''Dict of minimum width for each column. The dictionary keys are the
    column numbers, e.g. 0, 1, 2...

    .. versionadded:: 1.0.7

    :attr:`cols_minimum` is a :class:`~kivy.properties.DictProperty` and
    defaults to {}.
    '''

    rows_minimum = DictProperty({})
    '''Dict of minimum height for each row. The dictionary keys are the
    row numbers, e.g. 0, 1, 2...

    .. versionadded:: 1.0.7

    :attr:`rows_minimum` is a :class:`~kivy.properties.DictProperty` and
    defaults to {}.
    '''

    minimum_width = NumericProperty(0)
    '''Automatically computed minimum width needed to contain all children.

    .. versionadded:: 1.0.8

    :attr:`minimum_width` is a :class:`~kivy.properties.NumericProperty` and
    defaults to 0. It is read only.
    '''

    minimum_height = NumericProperty(0)
    '''Automatically computed minimum height needed to contain all children.

    .. versionadded:: 1.0.8

    :attr:`minimum_height` is a :class:`~kivy.properties.NumericProperty` and
    defaults to 0. It is read only.
    '''

    minimum_size = ReferenceListProperty(minimum_width, minimum_height)
    '''Automatically computed minimum size needed to contain all children.

    .. versionadded:: 1.0.8

    :attr:`minimum_size` is a
    :class:`~kivy.properties.ReferenceListProperty` of
    (:attr:`minimum_width`, :attr:`minimum_height`) properties. It is read
    only.
    '''

    orientation = OptionProperty('lr-tb',
                                 options=('lr-tb', 'tb-lr', 'rl-tb', 'tb-rl',
                                          'lr-bt', 'bt-lr', 'rl-bt', 'bt-rl'))
    '''Orientation of the layout.

    :attr:`orientation` is an :class:`~kivy.properties.OptionProperty` and
    defaults to 'lr-tb'.

    Valid orientations are 'lr-tb', 'tb-lr', 'rl-tb', 'tb-rl', 'lr-bt',
    'bt-lr', 'rl-bt' and 'bt-rl'.

    .. versionadded:: 2.0.0

    .. note::

        'lr' means Left to Right.
        'rl' means Right to Left.
        'tb' means Top to Bottom.
        'bt' means Bottom to Top.
    '''
    def __init__(self, **kwargs):
        self._cols = self._rows = None
        super(GridLayout, self).__init__(**kwargs)
        fbind = self.fbind
        update = self._trigger_layout
        fbind('col_default_width', update)
        fbind('row_default_height', update)
        fbind('col_force_default', update)
        fbind('row_force_default', update)
        fbind('cols', update)
        fbind('rows', update)
        fbind('parent', update)
        fbind('spacing', update)
        fbind('padding', update)
        fbind('children', update)
        fbind('size', update)
        fbind('pos', update)
        fbind('orientation', update)

    def get_max_widgets(self):
        if self.cols and self.rows:
            return self.rows * self.cols
        else:
            return None

    def on_children(self, instance, value):
        # if that makes impossible to construct things with deffered method,
        # migrate this test in do_layout, and/or issue a warning.
        smax = self.get_max_widgets()
        if smax and len(value) > smax:
            raise GridLayoutException(
                'Too many children in GridLayout. Increase rows/cols!')

    @property
    def _fills_row_first(self):
        return self.orientation[0] in 'lr'

    @property
    def _fills_from_left_to_right(self):
        return 'lr' in self.orientation

    @property
    def _fills_from_top_to_bottom(self):
        return 'tb' in self.orientation

    def _init_rows_cols_sizes(self, count):
        # the goal here is to calculate the minimum size of every cols/rows
        # and determine if they have stretch or not
        current_cols = self.cols
        current_rows = self.rows

        # if no cols or rows are set, we can't calculate minimum size.
        # the grid must be contrained at least on one side
        if not current_cols and not current_rows:
            Logger.warning('%r have no cols or rows set, '
                           'layout is not triggered.' % self)
            return

        if current_cols is None:
            current_cols = int(ceil(count / float(current_rows)))
        elif current_rows is None:
            current_rows = int(ceil(count / float(current_cols)))

        current_cols = max(1, current_cols)
        current_rows = max(1, current_rows)

        self._has_hint_bound_x = False
        self._has_hint_bound_y = False
        self._cols_min_size_none = 0.  # min size from all the None hint
        self._rows_min_size_none = 0.  # min size from all the None hint
        self._cols = cols = [self.col_default_width] * current_cols
        self._cols_sh = [None] * current_cols
        self._cols_sh_min = [None] * current_cols
        self._cols_sh_max = [None] * current_cols
        self._rows = rows = [self.row_default_height] * current_rows
        self._rows_sh = [None] * current_rows
        self._rows_sh_min = [None] * current_rows
        self._rows_sh_max = [None] * current_rows

        # update minimum size from the dicts
        items = (i for i in self.cols_minimum.items() if i[0] < len(cols))
        for index, value in items:
            cols[index] = max(value, cols[index])

        items = (i for i in self.rows_minimum.items() if i[0] < len(rows))
        for index, value in items:
            rows[index] = max(value, rows[index])
        return True

    def _fill_rows_cols_sizes(self):
        cols, rows = self._cols, self._rows
        cols_sh, rows_sh = self._cols_sh, self._rows_sh
        cols_sh_min, rows_sh_min = self._cols_sh_min, self._rows_sh_min
        cols_sh_max, rows_sh_max = self._cols_sh_max, self._rows_sh_max

        # calculate minimum size for each columns and rows
        has_bound_y = has_bound_x = False
        idx_iter = self._create_idx_iter(len(cols), len(rows))
        for child, (col, row) in zip(reversed(self.children), idx_iter):
            (shw, shh), (w, h) = child.size_hint, child.size
            shw_min, shh_min = child.size_hint_min
            shw_max, shh_max = child.size_hint_max

            # compute minimum size / maximum stretch needed
            if shw is None:
                cols[col] = nmax(cols[col], w)
            else:
                cols_sh[col] = nmax(cols_sh[col], shw)
                if shw_min is not None:
                    has_bound_x = True
                    cols_sh_min[col] = nmax(cols_sh_min[col], shw_min)
                if shw_max is not None:
                    has_bound_x = True
                    cols_sh_max[col] = nmin(cols_sh_max[col], shw_max)

            if shh is None:
                rows[row] = nmax(rows[row], h)
            else:
                rows_sh[row] = nmax(rows_sh[row], shh)
                if shh_min is not None:
                    has_bound_y = True
                    rows_sh_min[row] = nmax(rows_sh_min[row], shh_min)
                if shh_max is not None:
                    has_bound_y = True
                    rows_sh_max[row] = nmin(rows_sh_max[row], shh_max)
        self._has_hint_bound_x = has_bound_x
        self._has_hint_bound_y = has_bound_y

    def _update_minimum_size(self):
        # calculate minimum width/height needed, starting from padding +
        # spacing
        l, t, r, b = self.padding
        spacing_x, spacing_y = self.spacing
        cols, rows = self._cols, self._rows

        width = l + r + spacing_x * (len(cols) - 1)
        self._cols_min_size_none = sum(cols) + width
        # we need to subtract for the sh_max/min the already guaranteed size
        # due to having a None in the col. So sh_min gets smaller by that size
        # since it's already covered. Similarly for sh_max, because if we
        # already exceeded the max, the subtracted max will be zero, so
        # it won't get larger
        if self._has_hint_bound_x:
            cols_sh_min = self._cols_sh_min
            cols_sh_max = self._cols_sh_max

            for i, (c, sh_min,
                    sh_max) in enumerate(zip(cols, cols_sh_min, cols_sh_max)):
                if sh_min is not None:
                    width += max(c, sh_min)
                    cols_sh_min[i] = max(0., sh_min - c)
                else:
                    width += c

                if sh_max is not None:
                    cols_sh_max[i] = max(0., sh_max - c)
        else:
            width = self._cols_min_size_none

        height = t + b + spacing_y * (len(rows) - 1)
        self._rows_min_size_none = sum(rows) + height
        if self._has_hint_bound_y:
            rows_sh_min = self._rows_sh_min
            rows_sh_max = self._rows_sh_max

            for i, (r, sh_min,
                    sh_max) in enumerate(zip(rows, rows_sh_min, rows_sh_max)):
                if sh_min is not None:
                    height += max(r, sh_min)
                    rows_sh_min[i] = max(0., sh_min - r)
                else:
                    height += r

                if sh_max is not None:
                    rows_sh_max[i] = max(0., sh_max - r)
        else:
            height = self._rows_min_size_none

        # finally, set the minimum size
        self.minimum_size = (width, height)

    def _finalize_rows_cols_sizes(self):
        selfw = self.width
        selfh = self.height

        # resolve size for each column
        if self.col_force_default:
            cols = [self.col_default_width] * len(self._cols)
            for index, value in self.cols_minimum.items():
                cols[index] = value
            self._cols = cols
        else:
            cols = self._cols
            cols_sh = self._cols_sh
            cols_sh_min = self._cols_sh_min
            cols_weight = float(sum((x for x in cols_sh if x is not None)))
            stretch_w = max(0., selfw - self._cols_min_size_none)

            if stretch_w > 1e-9:
                if self._has_hint_bound_x:
                    # fix the hints to be within bounds
                    self.layout_hint_with_bounds(
                        cols_weight, stretch_w,
                        sum((c for c in cols_sh_min if c is not None)),
                        cols_sh_min, self._cols_sh_max, cols_sh)

                for index, col_stretch in enumerate(cols_sh):
                    # if the col don't have stretch information, nothing to do
                    if not col_stretch:
                        continue
                    # add to the min width whatever remains from size_hint
                    cols[index] += stretch_w * col_stretch / cols_weight

        # same algo for rows
        if self.row_force_default:
            rows = [self.row_default_height] * len(self._rows)
            for index, value in self.rows_minimum.items():
                rows[index] = value
            self._rows = rows
        else:
            rows = self._rows
            rows_sh = self._rows_sh
            rows_sh_min = self._rows_sh_min
            rows_weight = float(sum((x for x in rows_sh if x is not None)))
            stretch_h = max(0., selfh - self._rows_min_size_none)

            if stretch_h > 1e-9:
                if self._has_hint_bound_y:
                    # fix the hints to be within bounds
                    self.layout_hint_with_bounds(
                        rows_weight, stretch_h,
                        sum((r for r in rows_sh_min if r is not None)),
                        rows_sh_min, self._rows_sh_max, rows_sh)

                for index, row_stretch in enumerate(rows_sh):
                    # if the row don't have stretch information, nothing to do
                    if not row_stretch:
                        continue
                    # add to the min height whatever remains from size_hint
                    rows[index] += stretch_h * row_stretch / rows_weight

    def _iterate_layout(self, count):
        orientation = self.orientation
        padding = self.padding
        spacing_x, spacing_y = self.spacing

        cols = self._cols
        if self._fills_from_left_to_right:
            x_iter = accumulate(
                chain(
                    (self.x + padding[0], ),
                    (col_width + spacing_x
                     for col_width in islice(cols,
                                             len(cols) - 1)),
                ))
        else:
            x_iter = accumulate(
                chain(
                    (self.right - padding[2] - cols[-1], ),
                    (col_width + spacing_x
                     for col_width in islice(reversed(cols), 1, None)),
                ), sub)
            cols = reversed(cols)

        rows = self._rows
        if self._fills_from_top_to_bottom:
            y_iter = accumulate(
                chain(
                    (self.top - padding[1] - rows[0], ),
                    (row_height + spacing_y
                     for row_height in islice(rows, 1, None)),
                ), sub)
        else:
            y_iter = accumulate(
                chain(
                    (self.y + padding[3], ),
                    (row_height + spacing_y
                     for row_height in islice(reversed(rows),
                                              len(rows) - 1)),
                ))
            rows = reversed(rows)

        if self._fills_row_first:
            for i, (y, x), (row_height,
                            col_width) in zip(reversed(range(count)),
                                              product(y_iter, x_iter),
                                              product(rows, cols)):
                yield i, x, y, col_width, row_height
        else:
            for i, (x, y), (col_width,
                            row_height) in zip(reversed(range(count)),
                                               product(x_iter, y_iter),
                                               product(cols, rows)):
                yield i, x, y, col_width, row_height

    def do_layout(self, *largs):
        children = self.children
        if not children or not self._init_rows_cols_sizes(len(children)):
            l, t, r, b = self.padding
            self.minimum_size = l + r, t + b
            return
        self._fill_rows_cols_sizes()
        self._update_minimum_size()
        self._finalize_rows_cols_sizes()

        for i, x, y, w, h in self._iterate_layout(len(children)):
            c = children[i]
            c.pos = x, y
            shw, shh = c.size_hint
            shw_min, shh_min = c.size_hint_min
            shw_max, shh_max = c.size_hint_max

            if shw_min is not None:
                if shw_max is not None:
                    w = max(min(w, shw_max), shw_min)
                else:
                    w = max(w, shw_min)
            else:
                if shw_max is not None:
                    w = min(w, shw_max)

            if shh_min is not None:
                if shh_max is not None:
                    h = max(min(h, shh_max), shh_min)
                else:
                    h = max(h, shh_min)
            else:
                if shh_max is not None:
                    h = min(h, shh_max)

            if shw is None:
                if shh is not None:
                    c.height = h
            else:
                if shh is None:
                    c.width = w
                else:
                    c.size = (w, h)

    def _create_idx_iter(self, n_cols, n_rows):
        col_indices = range(n_cols) if self._fills_from_left_to_right \
            else range(n_cols - 1, -1, -1)
        row_indices = range(n_rows) if self._fills_from_top_to_bottom \
            else range(n_rows - 1, -1, -1)

        if self._fills_row_first:
            return (
                (col_index, row_index)
                for row_index, col_index in product(row_indices, col_indices))
        else:
            return product(col_indices, row_indices)
コード例 #17
0
class TransitionBase(EventDispatcher):
    '''TransitionBase is used to animate 2 screens within the
    :class:`ScreenManager`. This class acts as a base for other
    implementations like the :class:`SlideTransition` and
    :class:`SwapTransition`.

    :Events:
        `on_progress`: Transition object, progression float
            Fired during the animation of the transition.
        `on_complete`: Transition object
            Fired when the transition is fininshed.
    '''

    screen_out = ObjectProperty()
    '''Property that contains the screen to hide.
    Automatically set by the :class:`ScreenManager`.

    :class:`screen_out` is an :class:`~kivy.properties.ObjectProperty` and
    defaults to None.
    '''

    screen_in = ObjectProperty()
    '''Property that contains the screen to show.
    Automatically set by the :class:`ScreenManager`.

    :class:`screen_in` is an :class:`~kivy.properties.ObjectProperty` and
    defaults to None.
    '''

    duration = NumericProperty(.4)
    '''Duration in seconds of the transition.

    :class:`duration` is a :class:`~kivy.properties.NumericProperty` and
    defaults to .4 (= 400ms).

    .. versionchanged:: 1.8.0

        Default duration has been changed from 700ms to 400ms.
    '''

    manager = ObjectProperty()
    ''':class:`ScreenManager` object, set when the screen is added to a
    manager.

    :attr:`manager` is an :class:`~kivy.properties.ObjectProperty` and
    defaults to None, read-only.

    '''

    is_active = BooleanProperty(False)
    '''Indicate whether the transition is currently active or not.

    :attr:`is_active` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to False, read-only.
    '''

    # privates

    _anim = ObjectProperty(allownone=True)

    __events__ = ('on_progress', 'on_complete')

    def start(self, manager):
        '''(internal) Starts the transition. This is automatically
        called by the :class:`ScreenManager`.
        '''
        if self.is_active:
            raise ScreenManagerException('start() is called twice!')
        self.manager = manager
        self._anim = Animation(d=self.duration, s=0)
        self._anim.bind(on_progress=self._on_progress,
                        on_complete=self._on_complete)

        self.add_screen(self.screen_in)
        self.screen_in.transition_progress = 0.
        self.screen_in.transition_state = 'in'
        self.screen_out.transition_progress = 0.
        self.screen_out.transition_state = 'out'
        self.screen_in.dispatch('on_pre_enter')
        self.screen_out.dispatch('on_pre_leave')

        self.is_active = True
        self._anim.start(self)
        self.dispatch('on_progress', 0)

    def stop(self):
        '''(internal) Stops the transition. This is automatically called by the
        :class:`ScreenManager`.
        '''
        if self._anim:
            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 to the :class:`ScreenManager`.
        '''
        self.manager.real_add_widget(screen)

    def remove_screen(self, screen):
        '''(internal) Used to remove a screen from the :class:`ScreenManager`.
        '''
        self.manager.real_remove_widget(screen)

    def on_complete(self):
        self.remove_screen(self.screen_out)

    def on_progress(self, progression):
        pass

    def _on_progress(self, *l):
        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.is_active = False
        self.dispatch('on_complete')
        self.screen_in.dispatch('on_enter')
        self.screen_out.dispatch('on_leave')
        self._anim = None
コード例 #18
0
class Screen(RelativeLayout):
    '''Screen is an element intended to be used with a :class:`ScreenManager`.
    Check module documentation for more information.

    :Events:
        `on_pre_enter`: ()
            Event fired when the screen is about to be used: the entering
            animation is started.
        `on_enter`: ()
            Event fired when the screen is displayed: the entering animation is
            complete.
        `on_pre_leave`: ()
            Event fired when the screen is about to be removed: the leaving
            animation is started.
        `on_leave`: ()
            Event fired when the screen is removed: the leaving animation is
            finished.

    .. versionchanged:: 1.6.0
        Events `on_pre_enter`, `on_enter`, `on_pre_leave` and `on_leave` were
        added.
    '''

    name = StringProperty('')
    '''
    Name of the screen which must be unique within a :class:`ScreenManager`.
    This is the name used for :attr:`ScreenManager.current`.

    :attr:`name` is a :class:`~kivy.properties.StringProperty` and defaults to
    ''.
    '''

    manager = ObjectProperty(None, allownone=True)
    ''':class:`ScreenManager` object, set when the screen is added to a
    manager.

    :attr:`manager` is an :class:`~kivy.properties.ObjectProperty` and
    defaults to None, read-only.

    '''

    transition_progress = NumericProperty(0.)
    '''Value that represents the completion of the current transition, if any
    is occuring.

    If a transition is in progress, whatever the mode, the value will change
    from 0 to 1. If you want to know if it's an entering or leaving animation,
    check the :attr:`transition_state`.

    :attr:`transition_progress` is a :class:`~kivy.properties.NumericProperty`
    and defaults to 0.
    '''

    transition_state = OptionProperty('out', options=('in', 'out'))
    '''Value that represents the state of the transition:

    - 'in' if the transition is going to show your screen
    - 'out' if the transition is going to hide your screen

    After the transition is complete, the state will retain it's last value (in
    or out).

    :attr:`transition_state` is an :class:`~kivy.properties.OptionProperty` and
    defaults to 'out'.
    '''

    __events__ = ('on_pre_enter', 'on_enter', 'on_pre_leave', 'on_leave')

    def on_pre_enter(self, *args):
        pass

    def on_enter(self, *args):
        pass

    def on_pre_leave(self, *args):
        pass

    def on_leave(self, *args):
        pass

    def __repr__(self):
        return '<Screen name=%r>' % self.name
コード例 #19
0
ファイル: view_widgets.py プロジェクト: cplab/ceed
class MEAArrayAlign(Scatter):

    num_rows = NumericProperty(12)

    num_cols = NumericProperty(12)

    pitch = NumericProperty(20)

    diameter = NumericProperty(3)

    show = BooleanProperty(False)

    color = None

    label = None

    label2 = None

    def __init__(self, **kwargs):
        super(MEAArrayAlign, self).__init__(**kwargs)
        label = self.label = Factory.XYSizedLabel(text='A1')
        self.add_widget(label)
        label2 = self.label2 = Factory.XYSizedLabel(text='M1')
        self.add_widget(label2)
        self.fbind('num_rows', self.update_graphics)
        self.fbind('num_cols', self.update_graphics)
        self.fbind('pitch', self.update_graphics)
        self.fbind('diameter', self.update_graphics)
        self.update_graphics()

        def track_show(*largs):
            label.color = 1, 1, 1, (1 if self.show else 0)
            label2.color = 1, 1, 1, (1 if self.show else 0)

        self.fbind('show', track_show)
        track_show()

    def update_graphics(self, *largs):
        self.canvas.remove_group('MEAArrayAlign')
        pitch = self.pitch
        radius = self.diameter / 2.0

        with self.canvas:
            self.color = Color(1,
                               1,
                               1,
                               1 if self.show else 0,
                               group='MEAArrayAlign')
            for row in range(self.num_rows):
                for col in range(self.num_cols):
                    Point(points=[col * pitch, row * pitch],
                          pointsize=radius,
                          group='MEAArrayAlign')

        h = max((self.num_rows - 1) * pitch, 0)
        w = max((self.num_cols - 1) * pitch, 0)
        self.label.y = h
        self.label2.y = 0
        self.label2.right = self.label.right = w
        self.size = w, h + 35

    def on_touch_down(self, touch):
        if not self.do_translation_x and \
                not self.do_translation_y and \
                not self.do_rotation and \
                not self.do_scale:
            return False

        return super(MEAArrayAlign, self).on_touch_down(touch)

    def on_touch_move(self, touch):
        if not self.do_translation_x and \
                not self.do_translation_y and \
                not self.do_rotation and \
                not self.do_scale:
            return False

        return super(MEAArrayAlign, self).on_touch_move(touch)

    def on_touch_up(self, touch):
        if not self.do_translation_x and \
                not self.do_translation_y and \
                not self.do_rotation and \
                not self.do_scale:
            return False

        return super(MEAArrayAlign, self).on_touch_up(touch)

    @staticmethod
    def make_matrix(elems):
        mat = Matrix()
        mat.set(array=elems)
        return mat

    @staticmethod
    def compare_mat(mat, mat_list):
        return mat.tolist() == tuple(tuple(item) for item in mat_list)
コード例 #20
0
class Car(Widget):
    
    angle = NumericProperty(0)
    rotation = NumericProperty(0)
    velocity_x = NumericProperty(0)
    velocity_y = NumericProperty(0)
    velocity = ReferenceListProperty(velocity_x, velocity_y)
    sensor1_x = NumericProperty(0)
    sensor1_y = NumericProperty(0)
    sensor1 = ReferenceListProperty(sensor1_x, sensor1_y)
    sensor2_x = NumericProperty(0)
    sensor2_y = NumericProperty(0)
    sensor2 = ReferenceListProperty(sensor2_x, sensor2_y)
    sensor3_x = NumericProperty(0)
    sensor3_y = NumericProperty(0)
    sensor3 = ReferenceListProperty(sensor3_x, sensor3_y)
    signal1 = NumericProperty(0)
    signal2 = NumericProperty(0)
    signal3 = NumericProperty(0)

    def move(self, rotation):
        self.pos = Vector(*self.velocity) + self.pos
        self.rotation = rotation
        self.angle = self.angle + self.rotation
        self.sensor1 = Vector(30, 0).rotate(self.angle) + self.pos
        self.sensor2 = Vector(30, 0).rotate((self.angle+30)%360) + self.pos
        self.sensor3 = Vector(30, 0).rotate((self.angle-30)%360) + self.pos
        self.signal1 = int(np.sum(sand[int(self.sensor1_x)-10:int(self.sensor1_x)+10, int(self.sensor1_y)-10:int(self.sensor1_y)+10]))/400.
        self.signal2 = int(np.sum(sand[int(self.sensor2_x)-10:int(self.sensor2_x)+10, int(self.sensor2_y)-10:int(self.sensor2_y)+10]))/400.
        self.signal3 = int(np.sum(sand[int(self.sensor3_x)-10:int(self.sensor3_x)+10, int(self.sensor3_y)-10:int(self.sensor3_y)+10]))/400.
        if self.sensor1_x>longueur-10 or self.sensor1_x<10 or self.sensor1_y>largeur-10 or self.sensor1_y<10:
            self.signal1 = 1.
        if self.sensor2_x>longueur-10 or self.sensor2_x<10 or self.sensor2_y>largeur-10 or self.sensor2_y<10:
            self.signal2 = 1.
        if self.sensor3_x>longueur-10 or self.sensor3_x<10 or self.sensor3_y>largeur-10 or self.sensor3_y<10:
            self.signal3 = 1.
コード例 #21
0
ファイル: __init__.py プロジェクト: LCPallares/kivystudio
class CodePlace(BoxLayout):

    code_manager = ObjectProperty(None)

    tab_manager = ObjectProperty(None)

    new_empty_tab = NumericProperty(0)
    '''count of empty tabs that has been opened
    '''
    def __init__(self, **kwargs):
        super(CodePlace, self).__init__(**kwargs)
        self.code_manager = CodeScreenManager()

        self.add_widget(self.code_manager)
        Window.bind(on_key_down=self.keyboard_down)
        Window.bind(on_dropfile=self.file_droped)

    def file_droped(self, window, filename, *args):
        if self.collide_point(*window.mouse_pos):
            print('File droped on code input')
            if filename:
                self.add_code_tab(filename=filename)

    def add_widget(self, widget, tab_type=''):
        if len(self.children) > 1:
            if tab_type == 'code' or tab_type == 'new_file':
                tab = TabToggleButton(text=os.path.split(widget.filename)[1],
                                      filename=widget.filename)
                widget.tab = tab
                widget.tab_type = tab_type
                self.code_manager.add_widget(widget,
                                             widget.filename,
                                             tab_type=tab_type)

            elif tab_type == 'welcome':
                self.code_manager.add_widget(widget,
                                             'kivystudiowelcome',
                                             tab_type=tab_type)
                tab = TabToggleButton(text='Welcome',
                                      filename='kivystudiowelcome')

            tab.bind(state=self.change_screen)
            self.tab_manager.add_widget(tab)
            Clock.schedule_once(lambda dt: setattr(tab, 'state', 'down'))

        else:
            super(CodePlace, self).add_widget(widget)

    def change_screen(self, tab, state):
        if state == 'down':
            self.code_manager.current = tab.filename
            checked_list = list(
                filter(lambda child: child != tab,
                       ToggleButtonBehavior.get_widgets(tab.group)))
            for child in checked_list:
                if child != tab:
                    child.state = 'normal'

    def keyboard_down(self, window, *args):

        if args[0] == 9 and args[3] == ['ctrl'
                                        ]:  # switching screen with ctrl tab
            self.code_manager.current = self.code_manager.next()
            return True

        if args[0] == 119 and args[3] == ['ctrl']:  # close tab
            name = self.code_manager.get_screen(self.code_manager.current).name
            tab = get_tab_from_group(name)
            self.remove_code_tab(tab)

    def remove_code_tab(self, tab):
        self.tab_manager.remove_widget(tab)
        codeinput = self.code_manager.get_children_with_filename(tab.filename)
        self.code_manager.remove_widget(codeinput)

        if tab.filename.startswith('Untitled-') and not os.path.exists(
                tab.filename):
            self.new_empty_tab -= 1

    def add_code_tab(self, filename='', tab_type='code'):
        if filename:
            try:
                self.code_manager.get_screen(filename)
            except ScreenManagerException:  # then it is not added
                self.add_widget(FullCodeInput(filename=filename),
                                tab_type=tab_type)

        elif tab_type == 'new_file':  # a new tab
            self.new_empty_tab += 1
            while True:
                try:
                    self.code_manager.get_screen(filename)
                except ScreenManagerException:  # then it is not added
                    filename = 'Untitled-{}'.format(self.new_empty_tab)
                    self.add_widget(FullCodeInput(filename=filename),
                                    tab_type=tab_type)
                    return
                self.new_empty_tab += 1

        elif tab_type == 'welcome':
            try:
                self.code_manager.get_screen('kivystudiowelcome')
            except ScreenManagerException:  # then it is not added
                self.add_widget(WelcomeTab(), tab_type=tab_type)
コード例 #22
0
ファイル: list.py プロジェクト: vinidiktov/KivyMD
class BaseListItem(ThemableBehavior, RectangularRippleBehavior, ButtonBehavior,
                   FloatLayout):
    '''Base class to all ListItems. Not supposed to be instantiated on its own.
    '''

    text = StringProperty()
    '''Text shown in the first line.

    :attr:`text` is a :class:`~kivy.properties.StringProperty` and defaults
    to "".
    '''

    text_color = ListProperty(None)
    ''' Text color used if theme_text_color is set to 'Custom' '''

    font_style = OptionProperty('Subhead',
                                options=[
                                    'Body1', 'Body2', 'Caption', 'Subhead',
                                    'Title', 'Headline', 'Display1',
                                    'Display2', 'Display3', 'Display4',
                                    'Button', 'Icon'
                                ])

    theme_text_color = StringProperty('Primary', allownone=True)
    ''' Theme text color for primary text '''

    secondary_text = StringProperty()
    '''Text shown in the second and potentially third line.

    The text will wrap into the third line if the ListItem's type is set to
    \'one-line\'. It can be forced into the third line by adding a \\n
    escape sequence.

    :attr:`secondary_text` is a :class:`~kivy.properties.StringProperty` and
    defaults to "".
    '''

    secondary_text_color = ListProperty(None)
    ''' Text color used for secondary text if secondary_theme_text_color 
    is set to 'Custom' '''

    secondary_theme_text_color = StringProperty('Secondary', allownone=True)
    ''' Theme text color for secondary primary text '''

    secondary_font_style = OptionProperty('Body1',
                                          options=[
                                              'Body1', 'Body2', 'Caption',
                                              'Subhead', 'Title', 'Headline',
                                              'Display1', 'Display2',
                                              'Display3', 'Display4', 'Button',
                                              'Icon'
                                          ])

    divider = OptionProperty('Full',
                             options=['Full', 'Inset', None],
                             allownone=True)

    _txt_left_pad = NumericProperty(dp(16))
    _txt_top_pad = NumericProperty()
    _txt_bot_pad = NumericProperty()
    _txt_right_pad = NumericProperty(m_res.HORIZ_MARGINS)
    _num_lines = 2
コード例 #23
0
ファイル: race.py プロジェクト: prospero-apps/python
class PlayerStats(BoxLayout):
    name = StringProperty('')
    money = NumericProperty(0)
コード例 #24
0
ファイル: list.py プロジェクト: vinidiktov/KivyMD
class ThreeLineIconListItem(ContainerSupport, ThreeLineListItem):
    _txt_left_pad = NumericProperty(dp(72))
コード例 #25
0
ファイル: race.py プロジェクト: prospero-apps/python
class SlugImage(RelativeLayout):
    body_image = StringProperty('')
    eye_image = StringProperty('')
    y_position = NumericProperty(0)
コード例 #26
0
ファイル: list.py プロジェクト: vinidiktov/KivyMD
class ThreeLineRightIconListItem(ContainerSupport, ThreeLineListItem):
    # dp(40) = dp(16) + dp(24):
    _txt_right_pad = NumericProperty(dp(40) + m_res.HORIZ_MARGINS)
コード例 #27
0
ファイル: graph_drives.py プロジェクト: yisea123/YaskawaCoE
class Graph(Widget):
    '''Graph class, see module documentation for more information.
    '''

    # triggers a full reload of graphics
    _trigger = ObjectProperty(None)
    # triggers only a repositioning of objects due to size/pos updates
    _trigger_size = ObjectProperty(None)
    # triggers only a update of colors, e.g. tick_color
    _trigger_color = ObjectProperty(None)
    # holds widget with the x-axis label
    _xlabel = ObjectProperty(None)
    # holds widget with the y-axis label
    _ylabel = ObjectProperty(None)
    # holds all the x-axis tick mark labels
    _x_grid_label = ListProperty([])
    # holds all the y-axis tick mark labels
    _y_grid_label = ListProperty([])
    # the mesh drawing all the ticks/grids
    _mesh_ticks = ObjectProperty(None)
    # the mesh which draws the surrounding rectangle
    _mesh_rect = ObjectProperty(None)
    # a list of locations of major and minor ticks. The values are not
    # but is in the axis min - max range
    _ticks_majorx = ListProperty([])
    _ticks_minorx = ListProperty([])
    _ticks_majory = ListProperty([])
    _ticks_minory = ListProperty([])

    tick_color = ListProperty([.25, .25, .25, 1])
    '''Color of the grid/ticks, default to 1/4. grey.
    '''

    background_color = ListProperty([0, 0, 0, 0])
    '''Color of the background, defaults to transparent
    '''

    border_color = ListProperty([1, 1, 1, 1])
    '''Color of the border, defaults to white
    '''

    label_options = DictProperty()
    '''Label options that will be passed to `:class:`kivy.uix.Label`.
    '''

    _with_stencilbuffer = BooleanProperty(True)
    '''Whether :class:`Graph`'s FBO should use FrameBuffer (True) or not (False).

    .. warning:: This property is internal and so should be used with care. It can break
    some other graphic instructions used by the :class:`Graph`, for example you can have
    problems when drawing :class:`SmoothLinePlot` plots, so use it only when you know
    what exactly you are doing.

    :data:`_with_stencilbuffer` is a :class:`~kivy.properties.BooleanProperty`, defaults
    to True.
    '''
    def __init__(self, **kwargs):
        super(Graph, self).__init__(**kwargs)

        with self.canvas:
            self._fbo = Fbo(size=self.size,
                            with_stencilbuffer=self._with_stencilbuffer)

        with self._fbo:
            self._background_color = Color(*self.background_color)
            self._background_rect = Rectangle(size=self.size)
            self._mesh_ticks_color = Color(*self.tick_color)
            self._mesh_ticks = Mesh(mode='lines')
            self._mesh_rect_color = Color(*self.border_color)
            self._mesh_rect = Mesh(mode='line_strip')

        with self.canvas:
            Color(1, 1, 1)
            self._fbo_rect = Rectangle(size=self.size,
                                       texture=self._fbo.texture)

        mesh = self._mesh_rect
        mesh.vertices = [0] * (5 * 4)
        mesh.indices = range(5)

        self._plot_area = StencilView()
        self.add_widget(self._plot_area)

        t = self._trigger = Clock.create_trigger(self._redraw_all)
        ts = self._trigger_size = Clock.create_trigger(self._redraw_size)
        tc = self._trigger_color = Clock.create_trigger(self._update_colors)

        self.bind(center=ts,
                  padding=ts,
                  precision=ts,
                  plots=ts,
                  x_grid=ts,
                  y_grid=ts,
                  draw_border=ts)
        self.bind(xmin=t,
                  xmax=t,
                  xlog=t,
                  x_ticks_major=t,
                  x_ticks_minor=t,
                  xlabel=t,
                  x_grid_label=t,
                  ymin=t,
                  ymax=t,
                  ylog=t,
                  y_ticks_major=t,
                  y_ticks_minor=t,
                  ylabel=t,
                  y_grid_label=t,
                  font_size=t,
                  label_options=t,
                  x_ticks_angle=t)
        self.bind(tick_color=tc, background_color=tc, border_color=tc)
        self._trigger()

    def add_widget(self, widget):
        if widget is self._plot_area:
            canvas = self.canvas
            self.canvas = self._fbo
        super(Graph, self).add_widget(widget)
        if widget is self._plot_area:
            self.canvas = canvas

    def remove_widget(self, widget):
        if widget is self._plot_area:
            canvas = self.canvas
            self.canvas = self._fbo
        super(Graph, self).remove_widget(widget)
        if widget is self._plot_area:
            self.canvas = canvas

    def _get_ticks(self, major, minor, log, s_min, s_max):
        if major and s_max > s_min:
            if log:
                s_min = log10(s_min)
                s_max = log10(s_max)
                # count the decades in min - max. This is in actual decades,
                # not logs.
                n_decades = floor(s_max - s_min)
                # for the fractional part of the last decade, we need to
                # convert the log value, x, to 10**x but need to handle
                # differently if the last incomplete decade has a decade
                # boundary in it
                if floor(s_min + n_decades) != floor(s_max):
                    n_decades += 1 - (10**(s_min + n_decades + 1) -
                                      10**s_max) / 10**floor(s_max + 1)
                else:
                    n_decades += ((10**s_max - 10**(s_min + n_decades)) /
                                  10**floor(s_max + 1))
                # this might be larger than what is needed, but we delete
                # excess later
                n_ticks_major = n_decades / float(major)
                n_ticks = int(
                    floor(n_ticks_major * (minor if minor >= 1. else 1.0))) + 2
                # in decade multiples, e.g. 0.1 of the decade, the distance
                # between ticks
                decade_dist = major / float(minor if minor else 1.0)

                points_minor = [0] * n_ticks
                points_major = [0] * n_ticks
                k = 0  # position in points major
                k2 = 0  # position in points minor
                # because each decade is missing 0.1 of the decade, if a tick
                # falls in < min_pos skip it
                min_pos = 0.1 - 0.00001 * decade_dist
                s_min_low = floor(s_min)
                # first real tick location. value is in fractions of decades
                # from the start we have to use decimals here, otherwise
                # floating point inaccuracies results in bad values
                start_dec = ceil((10**Decimal(s_min - s_min_low - 1)) /
                                 Decimal(decade_dist)) * decade_dist
                count_min = (0 if not minor else
                             floor(start_dec / decade_dist) % minor)
                start_dec += s_min_low
                count = 0  # number of ticks we currently have passed start
                while True:
                    # this is the current position in decade that we are.
                    # e.g. -0.9 means that we're at 0.1 of the 10**ceil(-0.9)
                    # decade
                    pos_dec = start_dec + decade_dist * count
                    pos_dec_low = floor(pos_dec)
                    diff = pos_dec - pos_dec_low
                    zero = abs(diff) < 0.001 * decade_dist
                    if zero:
                        # the same value as pos_dec but in log scale
                        pos_log = pos_dec_low
                    else:
                        pos_log = log10(
                            (pos_dec - pos_dec_low) * 10**ceil(pos_dec))
                    if pos_log > s_max:
                        break
                    count += 1
                    if zero or diff >= min_pos:
                        if minor and not count_min % minor:
                            points_major[k] = pos_log
                            k += 1
                        else:
                            points_minor[k2] = pos_log
                            k2 += 1
                    count_min += 1
            else:
                # distance between each tick
                tick_dist = major / float(minor if minor else 1.0)
                n_ticks = int(floor((s_max - s_min) / tick_dist) + 1)
                points_major = [
                    0
                ] * int(floor((s_max - s_min) / float(major)) + 1)
                points_minor = [0] * (n_ticks - len(points_major) + 1)
                k = 0  # position in points major
                k2 = 0  # position in points minor
                for m in range(0, n_ticks):
                    if minor and m % minor:
                        points_minor[k2] = m * tick_dist + s_min
                        k2 += 1
                    else:
                        points_major[k] = m * tick_dist + s_min
                        k += 1
            del points_major[k:]
            del points_minor[k2:]
        else:
            points_major = []
            points_minor = []
        return points_major, points_minor

    def _update_labels(self):
        xlabel = self._xlabel
        ylabel = self._ylabel
        x = self.x
        y = self.y
        width = self.width
        height = self.height
        padding = self.padding
        x_next = padding + x
        y_next = padding + y
        xextent = width + x
        yextent = height + y
        ymin = self.ymin
        ymax = self.ymax
        xmin = self.xmin
        precision = self.precision
        x_overlap = False
        y_overlap = False
        # set up x and y axis labels
        if xlabel:
            xlabel.text = self.xlabel
            xlabel.texture_update()
            xlabel.size = xlabel.texture_size
            xlabel.pos = int(x + width / 2. - xlabel.width / 2.), int(padding +
                                                                      y)
            y_next += padding + xlabel.height
        if ylabel:
            ylabel.text = self.ylabel
            ylabel.texture_update()
            ylabel.size = ylabel.texture_size
            ylabel.x = padding + x - (ylabel.width / 2. - ylabel.height / 2.)
            x_next += padding + ylabel.height
        xpoints = self._ticks_majorx
        xlabels = self._x_grid_label
        xlabel_grid = self.x_grid_label
        ylabel_grid = self.y_grid_label
        ypoints = self._ticks_majory
        ylabels = self._y_grid_label
        # now x and y tick mark labels
        if len(ylabels) and ylabel_grid:
            # horizontal size of the largest tick label, to have enough room
            funcexp = exp10 if self.ylog else identity
            funclog = log10 if self.ylog else identity
            ylabels[0].text = precision % funcexp(ypoints[0])
            ylabels[0].texture_update()
            y1 = ylabels[0].texture_size
            y_start = y_next + (padding + y1[1] if len(xlabels) and xlabel_grid
                                else 0) + \
                               (padding + y1[1] if not y_next else 0)
            yextent = y + height - padding - y1[1] / 2.

            ymin = funclog(ymin)
            ratio = (yextent - y_start) / float(funclog(ymax) - ymin)
            y_start -= y1[1] / 2.
            y1 = y1[0]
            for k in range(len(ylabels)):
                ylabels[k].text = precision % funcexp(ypoints[k])
                ylabels[k].texture_update()
                ylabels[k].size = ylabels[k].texture_size
                y1 = max(y1, ylabels[k].texture_size[0])
                ylabels[k].pos = (int(x_next),
                                  int(y_start + (ypoints[k] - ymin) * ratio))
            if len(ylabels) > 1 and ylabels[0].top > ylabels[1].y:
                y_overlap = True
            else:
                x_next += y1 + padding
        if len(xlabels) and xlabel_grid:
            funcexp = exp10 if self.xlog else identity
            funclog = log10 if self.xlog else identity
            # find the distance from the end that'll fit the last tick label
            xlabels[0].text = precision % funcexp(xpoints[-1])
            xlabels[0].texture_update()
            xextent = x + width - xlabels[0].texture_size[0] / 2. - padding
            # find the distance from the start that'll fit the first tick label
            if not x_next:
                xlabels[0].text = precision % funcexp(xpoints[0])
                xlabels[0].texture_update()
                x_next = padding + xlabels[0].texture_size[0] / 2.
            xmin = funclog(xmin)
            ratio = (xextent - x_next) / float(funclog(self.xmax) - xmin)
            right = -1
            for k in range(len(xlabels)):
                xlabels[k].text = precision % funcexp(xpoints[k])
                # update the size so we can center the labels on ticks
                xlabels[k].texture_update()
                xlabels[k].size = xlabels[k].texture_size
                half_ts = xlabels[k].texture_size[0] / 2.
                xlabels[k].pos = (int(x_next + (xpoints[k] - xmin) * ratio -
                                      half_ts), int(y_next))
                if xlabels[k].x < right:
                    x_overlap = True
                    break
                right = xlabels[k].right
            if not x_overlap:
                y_next += padding + xlabels[0].texture_size[1]
        # now re-center the x and y axis labels
        if xlabel:
            xlabel.x = int(x_next + (xextent - x_next) / 2. -
                           xlabel.width / 2.)
        if ylabel:
            ylabel.y = int(y_next + (yextent - y_next) / 2. -
                           ylabel.height / 2.)
            ylabel.angle = 90
        if x_overlap:
            for k in range(len(xlabels)):
                xlabels[k].text = ''
        if y_overlap:
            for k in range(len(ylabels)):
                ylabels[k].text = ''
        return x_next - x, y_next - y, xextent - x, yextent - y

    def _update_ticks(self, size):
        # re-compute the positions of the bounding rectangle
        mesh = self._mesh_rect
        vert = mesh.vertices
        if self.draw_border:
            s0, s1, s2, s3 = size
            vert[0] = s0
            vert[1] = s1
            vert[4] = s2
            vert[5] = s1
            vert[8] = s2
            vert[9] = s3
            vert[12] = s0
            vert[13] = s3
            vert[16] = s0
            vert[17] = s1
        else:
            vert[0:18] = [0 for k in range(18)]
        mesh.vertices = vert
        # re-compute the positions of the x/y axis ticks
        mesh = self._mesh_ticks
        vert = mesh.vertices
        start = 0
        xpoints = self._ticks_majorx
        ypoints = self._ticks_majory
        xpoints2 = self._ticks_minorx
        ypoints2 = self._ticks_minory
        ylog = self.ylog
        xlog = self.xlog
        xmin = self.xmin
        xmax = self.xmax
        if xlog:
            xmin = log10(xmin)
            xmax = log10(xmax)
        ymin = self.ymin
        ymax = self.ymax
        if ylog:
            ymin = log10(ymin)
            ymax = log10(ymax)
        if len(xpoints):
            top = size[3] if self.x_grid else metrics.dp(12) + size[1]
            ratio = (size[2] - size[0]) / float(xmax - xmin)
            for k in range(start, len(xpoints) + start):
                vert[k * 8] = size[0] + (xpoints[k - start] - xmin) * ratio
                vert[k * 8 + 1] = size[1]
                vert[k * 8 + 4] = vert[k * 8]
                vert[k * 8 + 5] = top
            start += len(xpoints)
        if len(xpoints2):
            top = metrics.dp(8) + size[1]
            ratio = (size[2] - size[0]) / float(xmax - xmin)
            for k in range(start, len(xpoints2) + start):
                vert[k * 8] = size[0] + (xpoints2[k - start] - xmin) * ratio
                vert[k * 8 + 1] = size[1]
                vert[k * 8 + 4] = vert[k * 8]
                vert[k * 8 + 5] = top
            start += len(xpoints2)
        if len(ypoints):
            top = size[2] if self.y_grid else metrics.dp(12) + size[0]
            ratio = (size[3] - size[1]) / float(ymax - ymin)
            for k in range(start, len(ypoints) + start):
                vert[k * 8 + 1] = size[1] + (ypoints[k - start] - ymin) * ratio
                vert[k * 8 + 5] = vert[k * 8 + 1]
                vert[k * 8] = size[0]
                vert[k * 8 + 4] = top
            start += len(ypoints)
        if len(ypoints2):
            top = metrics.dp(8) + size[0]
            ratio = (size[3] - size[1]) / float(ymax - ymin)
            for k in range(start, len(ypoints2) + start):
                vert[k * 8 +
                     1] = size[1] + (ypoints2[k - start] - ymin) * ratio
                vert[k * 8 + 5] = vert[k * 8 + 1]
                vert[k * 8] = size[0]
                vert[k * 8 + 4] = top
        mesh.vertices = vert

    x_axis = ListProperty([None])
    y_axis = ListProperty([None])

    def get_x_axis(self, axis=0):
        if axis == 0:
            return self.xlog, self.xmin, self.xmax
        info = self.x_axis[axis]
        return (info["log"], info["min"], info["max"])

    def get_y_axis(self, axis=0):
        if axis == 0:
            return self.ylog, self.ymin, self.ymax
        info = self.y_axis[axis]
        return (info["log"], info["min"], info["max"])

    def add_x_axis(self, xmin, xmax, xlog=False):
        data = {"log": xlog, "min": xmin, "max": xmax}
        self.x_axis.append(data)
        return data

    def add_y_axis(self, ymin, ymax, ylog=False):
        data = {"log": ylog, "min": ymin, "max": ymax}
        self.y_axis.append(data)
        return data

    def _update_plots(self, size):
        for plot in self.plots:
            xlog, xmin, xmax = self.get_x_axis(plot.x_axis)
            ylog, ymin, ymax = self.get_y_axis(plot.y_axis)
            plot._update(xlog, xmin, xmax, ylog, ymin, ymax, size)

    def _update_colors(self, *args):
        self._mesh_ticks_color.rgba = tuple(self.tick_color)
        self._background_color.rgba = tuple(self.background_color)
        self._mesh_rect_color.rgba = tuple(self.border_color)

    def _redraw_all(self, *args):
        # add/remove all the required labels
        xpoints_major, xpoints_minor = self._redraw_x(*args)
        ypoints_major, ypoints_minor = self._redraw_y(*args)

        mesh = self._mesh_ticks
        n_points = (len(xpoints_major) + len(xpoints_minor) +
                    len(ypoints_major) + len(ypoints_minor))
        mesh.vertices = [0] * (n_points * 8)
        mesh.indices = [k for k in range(n_points * 2)]
        self._redraw_size()

    def _redraw_x(self, *args):
        font_size = self.font_size
        if self.xlabel:
            xlabel = self._xlabel
            if not xlabel:
                xlabel = Label()
                self.add_widget(xlabel)
                self._xlabel = xlabel

            xlabel.font_size = font_size
            for k, v in self.label_options.items():
                setattr(xlabel, k, v)

        else:
            xlabel = self._xlabel
            if xlabel:
                self.remove_widget(xlabel)
                self._xlabel = None
        grids = self._x_grid_label
        xpoints_major, xpoints_minor = self._get_ticks(self.x_ticks_major,
                                                       self.x_ticks_minor,
                                                       self.xlog, self.xmin,
                                                       self.xmax)
        self._ticks_majorx = xpoints_major
        self._ticks_minorx = xpoints_minor

        if not self.x_grid_label:
            n_labels = 0
        else:
            n_labels = len(xpoints_major)

        for k in range(n_labels, len(grids)):
            self.remove_widget(grids[k])
        del grids[n_labels:]

        grid_len = len(grids)
        grids.extend([None] * (n_labels - len(grids)))
        for k in range(grid_len, n_labels):
            grids[k] = GraphRotatedLabel(font_size=font_size,
                                         angle=self.x_ticks_angle,
                                         **self.label_options)
            self.add_widget(grids[k])
        return xpoints_major, xpoints_minor

    def _redraw_y(self, *args):
        font_size = self.font_size
        if self.ylabel:
            ylabel = self._ylabel
            if not ylabel:
                ylabel = GraphRotatedLabel()
                self.add_widget(ylabel)
                self._ylabel = ylabel

            ylabel.font_size = font_size
            for k, v in self.label_options.items():
                setattr(ylabel, k, v)
        else:
            ylabel = self._ylabel
            if ylabel:
                self.remove_widget(ylabel)
                self._ylabel = None
        grids = self._y_grid_label
        ypoints_major, ypoints_minor = self._get_ticks(self.y_ticks_major,
                                                       self.y_ticks_minor,
                                                       self.ylog, self.ymin,
                                                       self.ymax)
        self._ticks_majory = ypoints_major
        self._ticks_minory = ypoints_minor

        if not self.y_grid_label:
            n_labels = 0
        else:
            n_labels = len(ypoints_major)

        for k in range(n_labels, len(grids)):
            self.remove_widget(grids[k])
        del grids[n_labels:]

        grid_len = len(grids)
        grids.extend([None] * (n_labels - len(grids)))
        for k in range(grid_len, n_labels):
            grids[k] = Label(font_size=font_size, **self.label_options)
            self.add_widget(grids[k])
        return ypoints_major, ypoints_minor

    def _redraw_size(self, *args):
        # size a 4-tuple describing the bounding box in which we can draw
        # graphs, it's (x0, y0, x1, y1), which correspond with the bottom left
        # and top right corner locations, respectively
        self._clear_buffer()
        size = self._update_labels()
        self.view_pos = self._plot_area.pos = (size[0], size[1])
        self.view_size = self._plot_area.size = (size[2] - size[0],
                                                 size[3] - size[1])

        if self.size[0] and self.size[1]:
            self._fbo.size = self.size
        else:
            self._fbo.size = 1, 1  # gl errors otherwise
        self._fbo_rect.texture = self._fbo.texture
        self._fbo_rect.size = self.size
        self._fbo_rect.pos = self.pos
        self._background_rect.size = self.size
        self._update_ticks(size)
        self._update_plots(size)

    def _clear_buffer(self, *largs):
        fbo = self._fbo
        fbo.bind()
        fbo.clear_buffer()
        fbo.release()

    def add_plot(self, plot):
        '''Add a new plot to this graph.

        :Parameters:
            `plot`:
                Plot to add to this graph.

        >>> graph = Graph()
        >>> plot = MeshLinePlot(mode='line_strip', color=[1, 0, 0, 1])
        >>> plot.points = [(x / 10., sin(x / 50.)) for x in range(-0, 101)]
        >>> graph.add_plot(plot)
        '''
        if plot in self.plots:
            return
        add = self._plot_area.canvas.add
        for instr in plot.get_drawings():
            add(instr)
        plot.bind(on_clear_plot=self._clear_buffer)
        self.plots.append(plot)

    def remove_plot(self, plot):
        '''Remove a plot from this graph.

        :Parameters:
            `plot`:
                Plot to remove from this graph.

        >>> graph = Graph()
        >>> plot = MeshLinePlot(mode='line_strip', color=[1, 0, 0, 1])
        >>> plot.points = [(x / 10., sin(x / 50.)) for x in range(-0, 101)]
        >>> graph.add_plot(plot)
        >>> graph.remove_plot(plot)
        '''
        if plot not in self.plots:
            return
        remove = self._plot_area.canvas.remove
        for instr in plot.get_drawings():
            remove(instr)
        plot.unbind(on_clear_plot=self._clear_buffer)
        self.plots.remove(plot)
        self._clear_buffer()

    def collide_plot(self, x, y):
        '''Determine if the given coordinates fall inside the plot area.

        :Parameters:
            `x, y`:
                The coordinates to test (in window coords).
        '''
        adj_x, adj_y = x - self._plot_area.pos[0], y - self._plot_area.pos[1]
        return 0 <= adj_x <= self._plot_area.size[0] \
               and 0 <= adj_y <= self._plot_area.size[1]

    def to_data(self, x, y):
        '''Convert window coords to data coords.

        :Parameters:
            `x, y`:
                The coordinates to convert (in window coords).
        '''
        adj_x = float(x - self._plot_area.pos[0])
        adj_y = float(y - self._plot_area.pos[1])
        norm_x = adj_x / self._plot_area.size[0]
        norm_y = adj_y / self._plot_area.size[1]
        if self.xlog:
            xmin, xmax = log10(self.xmin), log10(self.xmax)
            conv_x = 10.**(norm_x * (xmax - xmin) + xmin)
        else:
            conv_x = norm_x * (self.xmax - self.xmin) + self.xmin
        if self.ylog:
            ymin, ymax = log10(self.ymin), log10(self.ymax)
            conv_y = 10.**(norm_y * (ymax - ymin) + ymin)
        else:
            conv_y = norm_y * (self.ymax - self.ymin) + self.ymin
        return [conv_x, conv_y]

    xmin = NumericProperty(0.)
    '''The x-axis minimum value.

    If :data:`xlog` is True, xmin must be larger than zero.

    :data:`xmin` is a :class:`~kivy.properties.NumericProperty`, defaults to 0.
    '''

    xmax = NumericProperty(100.)
    '''The x-axis maximum value, larger than xmin.

    :data:`xmax` is a :class:`~kivy.properties.NumericProperty`, defaults to 0.
    '''

    xlog = BooleanProperty(False)
    '''Determines whether the x-axis should be displayed logarithmically (True)
    or linearly (False).

    :data:`xlog` is a :class:`~kivy.properties.BooleanProperty`, defaults
    to False.
    '''

    x_ticks_major = BoundedNumericProperty(0, min=0)
    '''Distance between major tick marks on the x-axis.

    Determines the distance between the major tick marks. Major tick marks
    start from min and re-occur at every ticks_major until :data:`xmax`.
    If :data:`xmax` doesn't overlap with a integer multiple of ticks_major,
    no tick will occur at :data:`xmax`. Zero indicates no tick marks.

    If :data:`xlog` is true, then this indicates the distance between ticks
    in multiples of current decade. E.g. if :data:`xmin` is 0.1 and
    ticks_major is 0.1, it means there will be a tick at every 10th of the
    decade, i.e. 0.1 ... 0.9, 1, 2... If it is 0.3, the ticks will occur at
    0.1, 0.3, 0.6, 0.9, 2, 5, 8, 10. You'll notice that it went from 8 to 10
    instead of to 20, that's so that we can say 0.5 and have ticks at every
    half decade, e.g. 0.1, 0.5, 1, 5, 10, 50... Similarly, if ticks_major is
    1.5, there will be ticks at 0.1, 5, 100, 5,000... Also notice, that there's
    always a major tick at the start. Finally, if e.g. :data:`xmin` is 0.6
    and this 0.5 there will be ticks at 0.6, 1, 5...

    :data:`x_ticks_major` is a
    :class:`~kivy.properties.BoundedNumericProperty`, defaults to 0.
    '''

    x_ticks_minor = BoundedNumericProperty(0, min=0)
    '''The number of sub-intervals that divide x_ticks_major.

    Determines the number of sub-intervals into which ticks_major is divided,
    if non-zero. The actual number of minor ticks between the major ticks is
    ticks_minor - 1. Only used if ticks_major is non-zero. If there's no major
    tick at xmax then the number of minor ticks after the last major
    tick will be however many ticks fit until xmax.

    If self.xlog is true, then this indicates the number of intervals the
    distance between major ticks is divided. The result is the number of
    multiples of decades between ticks. I.e. if ticks_minor is 10, then if
    ticks_major is 1, there will be ticks at 0.1, 0.2...0.9, 1, 2, 3... If
    ticks_major is 0.3, ticks will occur at 0.1, 0.12, 0.15, 0.18... Finally,
    as is common, if ticks major is 1, and ticks minor is 5, there will be
    ticks at 0.1, 0.2, 0.4... 0.8, 1, 2...

    :data:`x_ticks_minor` is a
    :class:`~kivy.properties.BoundedNumericProperty`, defaults to 0.
    '''

    x_grid = BooleanProperty(False)
    '''Determines whether the x-axis has tick marks or a full grid.

    If :data:`x_ticks_major` is non-zero, then if x_grid is False tick marks
    will be displayed at every major tick. If x_grid is True, instead of ticks,
    a vertical line will be displayed at every major tick.

    :data:`x_grid` is a :class:`~kivy.properties.BooleanProperty`, defaults
    to False.
    '''

    x_grid_label = BooleanProperty(False)
    '''Whether labels should be displayed beneath each major tick. If true,
    each major tick will have a label containing the axis value.

    :data:`x_grid_label` is a :class:`~kivy.properties.BooleanProperty`,
    defaults to False.
    '''

    xlabel = StringProperty('')
    '''The label for the x-axis. If not empty it is displayed in the center of
    the axis.

    :data:`xlabel` is a :class:`~kivy.properties.StringProperty`,
    defaults to ''.
    '''

    ymin = NumericProperty(0.)
    '''The y-axis minimum value.

    If :data:`ylog` is True, ymin must be larger than zero.

    :data:`ymin` is a :class:`~kivy.properties.NumericProperty`, defaults to 0.
    '''

    ymax = NumericProperty(100.)
    '''The y-axis maximum value, larger than ymin.

    :data:`ymax` is a :class:`~kivy.properties.NumericProperty`, defaults to 0.
    '''

    ylog = BooleanProperty(False)
    '''Determines whether the y-axis should be displayed logarithmically (True)
    or linearly (False).

    :data:`ylog` is a :class:`~kivy.properties.BooleanProperty`, defaults
    to False.
    '''

    y_ticks_major = BoundedNumericProperty(0, min=0)
    '''Distance between major tick marks. See :data:`x_ticks_major`.

    :data:`y_ticks_major` is a
    :class:`~kivy.properties.BoundedNumericProperty`, defaults to 0.
    '''

    y_ticks_minor = BoundedNumericProperty(0, min=0)
    '''The number of sub-intervals that divide ticks_major.
    See :data:`x_ticks_minor`.

    :data:`y_ticks_minor` is a
    :class:`~kivy.properties.BoundedNumericProperty`, defaults to 0.
    '''

    y_grid = BooleanProperty(False)
    '''Determines whether the y-axis has tick marks or a full grid. See
    :data:`x_grid`.

    :data:`y_grid` is a :class:`~kivy.properties.BooleanProperty`, defaults
    to False.
    '''

    y_grid_label = BooleanProperty(False)
    '''Whether labels should be displayed beneath each major tick. If true,
    each major tick will have a label containing the axis value.

    :data:`y_grid_label` is a :class:`~kivy.properties.BooleanProperty`,
    defaults to False.
    '''

    ylabel = StringProperty('')
    '''The label for the y-axis. If not empty it is displayed in the center of
    the axis.

    :data:`ylabel` is a :class:`~kivy.properties.StringProperty`,
    defaults to ''.
    '''

    padding = NumericProperty('5dp')
    '''Padding distances between the labels, axes titles and graph, as
    well between the widget and the objects near the boundaries.

    :data:`padding` is a :class:`~kivy.properties.NumericProperty`, defaults
    to 5dp.
    '''

    font_size = NumericProperty('15sp')
    '''Font size of the labels.

    :data:`font_size` is a :class:`~kivy.properties.NumericProperty`, defaults
    to 15sp.
    '''

    x_ticks_angle = NumericProperty(0)
    '''Rotate angle of the x-axis tick marks.

    :data:`x_ticks_angle` is a :class:`~kivy.properties.NumericProperty`,
    defaults to 0.
    '''

    precision = StringProperty('%g')
    '''Determines the numerical precision of the tick mark labels. This value
    governs how the numbers are converted into string representation. Accepted
    values are those listed in Python's manual in the
    "String Formatting Operations" section.

    :data:`precision` is a :class:`~kivy.properties.StringProperty`, defaults
    to '%g'.
    '''

    draw_border = BooleanProperty(True)
    '''Whether a border is drawn around the canvas of the graph where the
    plots are displayed.

    :data:`draw_border` is a :class:`~kivy.properties.BooleanProperty`,
    defaults to True.
    '''

    plots = ListProperty([])
    '''Holds a list of all the plots in the graph. To add and remove plots
    from the graph use :data:`add_plot` and :data:`add_plot`. Do not add
    directly edit this list.

    :data:`plots` is a :class:`~kivy.properties.ListProperty`,
    defaults to [].
    '''

    view_size = ObjectProperty((0, 0))
    '''The size of the graph viewing area - the area where the plots are
    displayed, excluding labels etc.
    '''

    view_pos = ObjectProperty((0, 0))
    '''The pos of the graph viewing area - the area where the plots are
コード例 #28
0
class Accordion(Widget):
    '''Accordion class. See module documentation for more information.
    '''

    orientation = OptionProperty('horizontal', options=(
        'horizontal', 'vertical'))
    '''Orientation of the layout.

    :attr:`orientation` is an :class:`~kivy.properties.OptionProperty`
    and defaults to 'horizontal'. Can take a value of 'vertical' or
    'horizontal'.

    '''

    anim_duration = NumericProperty(1)
    '''Duration of the animation in seconds when a new accordion item is
    selected.

    :attr:`anim_duration` is a :class:`~kivy.properties.NumericProperty` and
    defaults to .25 (250ms).
    '''

    anim_func = ObjectProperty('out_expo')
    '''Easing function to use for the animation. Check
    :class:`kivy.animation.AnimationTransition` for more information about
    available animation functions.

    :attr:`anim_func` is an :class:`~kivy.properties.ObjectProperty` and
    defaults to 'out_expo'. You can set a string or a function to use as an
    easing function.
    '''

    min_space = NumericProperty('44dp')
    '''Minimum space to use for the title of each item. This value is
    automatically set for each child every time the layout event occurs.

    :attr:`min_space` is a :class:`~kivy.properties.NumericProperty` and
    defaults to 44 (px).
    '''

    def __init__(self, **kwargs):
        super(Accordion, self).__init__(**kwargs)
        update = self._trigger_layout = \
            Clock.create_trigger(self._do_layout, -1)
        fbind = self.fbind
        fbind('orientation', update)
        fbind('children', update)
        fbind('size', update)
        fbind('pos', update)
        fbind('min_space', update)

    def add_widget(self, widget, *largs):
        if not isinstance(widget, AccordionItem):
            raise AccordionException('Accordion accept only AccordionItem')

        widget.accordion = self
        ret = super(Accordion, self).add_widget(widget, *largs)
        return ret

    def select(self, instance):
        if instance not in self.children:
            raise AccordionException(
                'Accordion: instance not found in children')
        for widget in self.children:
            widget.collapse = widget is not instance
        self._trigger_layout()

    def _do_layout(self, dt):
        children = self.children
        if children:
            all_collapsed = all(x.collapse for x in children)
        else:
            all_collapsed = False

        if all_collapsed:
            children[0].collapse = False

        orientation = self.orientation
        min_space = self.min_space
        min_space_total = len(children) * self.min_space
        w, h = self.size
        x, y = self.pos
        if orientation == 'horizontal':
            display_space = self.width - min_space_total
        else:
            display_space = self.height - min_space_total

        if display_space <= 0:
            Logger.warning('Accordion: not enough space '
                           'for displaying all children')
            Logger.warning('Accordion: need %dpx, got %dpx' % (
                min_space_total, min_space_total + display_space))
            Logger.warning('Accordion: layout aborted.')
            return

        if orientation == 'horizontal':
            children = reversed(children)

        for child in children:
            child_space = min_space
            child_space += display_space * (1 - child.collapse_alpha)
            child._min_space = min_space
            child.x = x
            child.y = y
            child.orientation = self.orientation
            if orientation == 'horizontal':
                child.content_size = display_space, h
                child.width = child_space
                child.height = h
                x += child_space
            else:
                child.content_size = w, display_space
                child.width = w
                child.height = child_space
                y += child_space
コード例 #29
0
class RootWidget(Screen):

    mapview = ObjectProperty()
    alpha = ListProperty([1])
    wx1 = NumericProperty(randint(10, Window.width))
    wy1 = NumericProperty(randint(10, Window.height))
    wx2 = NumericProperty(randint(10, Window.width))
    wy2 = NumericProperty(randint(10, Window.height))
    wx3 = NumericProperty(randint(10, Window.width))
    wy3 = NumericProperty(randint(10, Window.height))
    wx4 = NumericProperty(randint(10, Window.width))
    wy4 = NumericProperty(randint(10, Window.height))
    wx5 = NumericProperty(randint(10, Window.width))
    wy5 = NumericProperty(randint(10, Window.height))
    wx6 = NumericProperty(randint(10, Window.width))
    wy6 = NumericProperty(randint(10, Window.height))
    wx7 = NumericProperty(randint(10, Window.width))
    wy7 = NumericProperty(randint(10, Window.height))
    wx8 = NumericProperty(randint(10, Window.width))
    wy8 = NumericProperty(randint(10, Window.height))
    wx9 = NumericProperty(randint(10, Window.width))
    wy9 = NumericProperty(randint(10, Window.height))
    wx10 = NumericProperty(randint(10, Window.width))
    wy10 = NumericProperty(randint(10, Window.height))
    wx11 = NumericProperty(randint(10, Window.width))
    wy11 = NumericProperty(randint(10, Window.height))
    wx12 = NumericProperty(randint(10, Window.width))
    wy12 = NumericProperty(randint(10, Window.height))
    wx13 = NumericProperty(randint(10, Window.width))
    wy13 = NumericProperty(randint(10, Window.height))
    wx14 = NumericProperty(randint(10, Window.width))
    wy14 = NumericProperty(randint(10, Window.height))
    r1 = NumericProperty(randint(10, Window.height//6))
    r2 = NumericProperty(randint(10, Window.height//6))
    r3 = NumericProperty(randint(10, Window.height//6))
    r4 = NumericProperty(randint(10, Window.height//6))
    r5 = NumericProperty(randint(10, Window.height//6))
    r6 = NumericProperty(randint(10, Window.height//6))
    r7 = NumericProperty(randint(10, Window.height//6))
    r8 = NumericProperty(randint(10, Window.height//6))
    r9 = NumericProperty(randint(10, Window.height//6))
    r10 = NumericProperty(randint(10, Window.height//6))
    r11 = NumericProperty(randint(10, Window.height//6))
    r12 = NumericProperty(randint(10, Window.height//6))
    r13 = NumericProperty(randint(10, Window.height//6))
    r14 = NumericProperty(randint(10, Window.height//6))
コード例 #30
0
ファイル: test_properties.py プロジェクト: DanAlbert/kivy
    def test_reference(self):
        from kivy.properties import NumericProperty, ReferenceListProperty

        x = NumericProperty(0)
        x.link(wid, 'x')
        x.link_deps(wid, 'x')
        y = NumericProperty(0)
        y.link(wid, 'y')
        y.link_deps(wid, 'y')
        pos = ReferenceListProperty(x, y)
        pos.link(wid, 'pos')
        pos.link_deps(wid, 'pos')

        self.assertEqual(x.get(wid), 0)
        self.assertEqual(y.get(wid), 0)
        self.assertEqual(pos.get(wid), [0, 0])

        x.set(wid, 50)
        self.assertEqual(pos.get(wid), [50, 0])

        y.set(wid, 50)
        self.assertEqual(pos.get(wid), [50, 50])

        pos.set(wid, [0, 0])
        self.assertEqual(pos.get(wid), [0, 0])
        self.assertEqual(x.get(wid), 0)
        self.assertEqual(y.get(wid), 0)

        # test observer
        global observe_called
        observe_called = 0

        def observe(obj, value):
            global observe_called
            observe_called = 1
        pos.bind(wid, observe)

        self.assertEqual(observe_called, 0)
        x.set(wid, 99)
        self.assertEqual(observe_called, 1)
コード例 #31
0
ファイル: test_properties.py プロジェクト: 13768324554/kivy
    def test_numeric_string_with_units_check(self):
        from kivy.properties import NumericProperty

        a = NumericProperty()
        a.link(wid, 'a')
        a.link_deps(wid, 'a')
        self.assertEqual(a.get(wid), 0)

        a.set(wid, '55dp')
        from kivy.core.window import Window
        density = Window._density if hasattr(Window, '_density') else 1
        self.assertEqual(a.get(wid), 55 * density)
        self.assertEqual(a.get_format(wid), 'dp')

        a.set(wid, u'55dp')
        self.assertEqual(a.get(wid), 55 * density)
        self.assertEqual(a.get_format(wid), 'dp')

        a.set(wid, '99in')
        self.assertEqual(a.get(wid), 9504.0 * density)
        self.assertEqual(a.get_format(wid), 'in')

        a.set(wid, u'99in')
        self.assertEqual(a.get(wid), 9504.0 * density)
        self.assertEqual(a.get_format(wid), 'in')
コード例 #32
0
ファイル: SoccerStars.py プロジェクト: GAM-4-5/SoccerStars
class Igra(Widget):
    lopta = ObjectProperty(None)

    igrac1 = ObjectProperty(None)
    igrac2 = ObjectProperty(None)

    slijed = BooleanProperty(
        None)  #provjerava ako si kliknuo igraca koji je na redu
    red = NumericProperty(
        1)  #broji red odigranih koraka kako bi se znalo tko je na redu

    publika = SoundLoader.load("source/sound1.mp3").play()
    goal = SoundLoader.load("source/sound2.mp3")

    #kad se klikne provjerava koji je igrac kliknut
    def on_touch_down(self, touch):
        if self.igrac1.collide_point(*touch.pos):
            self.slijed = True
        elif self.igrac2.collide_point(*touch.pos):
            self.slijed = False

    #kad se otpusti klik, provjerava zadnja pozicija klika te se računa brzina koja se nadodaje igraču
    def on_touch_up(self, touch):
        if self.slijed and self.red % 2 == 1:
            self.igrac1.velocity_x = int(
                (self.igrac1.center_x - touch.x) * 3 / 4)
            self.igrac1.velocity_y = int(
                (self.igrac1.center_y - touch.y) * 3 / 4)
            self.slijed = BooleanProperty(None)
            self.red += 1
        elif self.red % 2 == 0 and not self.slijed:
            self.igrac2.velocity_x = int(
                (self.igrac2.center_x - touch.x) * 3 / 4)
            self.igrac2.velocity_y = int(
                (self.igrac2.center_y - touch.y) * 3 / 4)
            self.slijed = BooleanProperty(None)
            self.red += 1

    def restart(self):
        self.goal.play()
        self.lopta.center = (300, 454)
        self.lopta.velocity = (0, 0)
        self.igrac1.center = (300, 200)
        self.igrac1.velocity = (0, 0)
        self.igrac2.center = (300, 708)
        self.igrac2.velocity = (0, 0)

    def update(self, dt):
        #pokretanje funkcije kretanja igraca, 60x u sekundi provodi micanje igraca
        #provjerava i provodi odbijanje između igrača i igrača s loptom
        if self.igrac1.velocity_y != 0 or self.igrac2.velocity_x != 0:
            self.igrac1.move()
            self.igrac1.player_collide(self.igrac2)
            self.igrac1.player_collide(self.lopta)
        if self.igrac2.velocity_y != 0 or self.igrac2.velocity_y != 0:
            self.igrac2.move()
            self.igrac2.player_collide(self.igrac1)
            self.igrac2.player_collide(self.lopta)
        if self.lopta.velocity_y != 0 or self.lopta.velocity_x != 0:
            self.lopta.move()
            self.lopta.ball_collide(self.igrac1)
            self.lopta.ball_collide(self.igrac2)

        #Odbijanje od zidova terena
        if (self.igrac1.x <= 0) or (self.igrac1.right >= 600):
            self.igrac1.velocity_x *= -1
            self.igrac1.move()
        if (self.igrac1.y <= 0) or (self.igrac1.top >= 908):
            self.igrac1.velocity_y *= -1
            self.igrac1.move()
        if (self.igrac2.x <= 0) or (self.igrac2.right >= 600):
            self.igrac2.velocity_x *= -1
            self.igrac2.move()
        if (self.igrac2.y <= 0) or (self.igrac2.top >= 908):
            self.igrac2.velocity_y *= -1
            self.igrac2.move()

        #Odbijanje lopte od zidova i restartanje igre u slučaju gola
        if (self.lopta.x <= 0) or (self.lopta.right >= 600):
            self.lopta.velocity_x *= -1
            self.lopta.move()
        if (self.lopta.y <= 0):
            self.igrac2.score += 1
            self.restart()
        elif (self.lopta.top >= 908):
            self.igrac1.score += 1
            self.restart()
コード例 #33
0
ファイル: list.py プロジェクト: vinidiktov/KivyMD
class ThreeLineAvatarIconListItem(ThreeLineAvatarListItem):
    # dp(40) = dp(16) + dp(24):
    _txt_right_pad = NumericProperty(dp(40) + m_res.HORIZ_MARGINS)
コード例 #34
0
class PhysicsObject(Widget):
    angle = NumericProperty()
    scale = NumericProperty(1.0)
    source = StringProperty()
    color = ListProperty([1, 1, 1, 1])
    constraints = [0, 100, 0, 100]
    constraint_x = BooleanProperty(True)
    constraint_y = BooleanProperty(True)
    _vectors = {}
    _trajectory = collections.deque()
    _trajectory_points = 100
    _trajectory_resolution = 0.05
    show_trajectory = BooleanProperty(False)
    draggable = BooleanProperty(False)

    def __init__(self, **kwargs):
        self.register_event_type('on_drag')
        super(PhysicsObject, self).__init__(**kwargs)

    def add_vector(self,
                   name,
                   title,
                   length,
                   angle=0.0,
                   color=(1, 1, 1, 1),
                   mode='object'):
        self._vectors[name] = VectorWidget(title=title,
                                           length=length,
                                           angle=angle,
                                           color=color,
                                           mode=mode)
        self.add_widget(self._vectors[name])

    def update(self, dt):
        if len(self._trajectory) == 0:
            self._trajectory.appendleft((self.pos[0], self.pos[1]))
        angle0 = math.atan2(self._trajectory[0][1] - self.pos[1],
                            self._trajectory[0][0] - self.pos[0])
        if len(self._trajectory) > 1:
            angle1 = math.atan2(
                self._trajectory[1][1] - self._trajectory[0][1],
                self._trajectory[1][0] - self._trajectory[0][0])
        else:
            angle1 = 0
        if math.fabs(angle0 - angle1) > self._trajectory_resolution:
            self._trajectory.appendleft((self.pos[0], self.pos[1]))
            if len(self._trajectory) > self._trajectory_points:
                self._trajectory.pop()

    def after_update(self, dt):
        max_size = max(self.width, self.height) / 2
        if self.constraint_x:
            if self.x < self.constraints[0] + max_size:
                self.x = self.constraints[0] + max_size
            if self.x > self.constraints[1] - max_size:
                self.x = self.constraints[1] - max_size
        if self.constraint_y:
            if self.y < self.constraints[2] + max_size:
                self.y = self.constraints[2] + max_size
            if self.y > self.constraints[3] - max_size:
                self.y = self.constraints[3] - max_size

    def update_vector(self, name, length, angle=None):
        vector = self._vectors[name]
        vector.name = name
        vector.length = length
        if angle is not None:
            vector.angle = angle

    def on_pos(self, *largs):
        for vector in self._vectors.itervalues():
            vector.pos = self.pos

    def clear_trajectory(self):
        self._trajectory.clear()

    def init(self, *largs):
        self.clear_trajectory()

    def on_drag(self, touch):
        pass

    def collide_point(self, x, y):
        max_size = max(self.width, self.height) / 2
        return self.x - max_size < x < self.x + max_size and self.y - max_size < y < self.y + max_size

    def on_touch_down(self, touch):
        if super(PhysicsObject, self).on_touch_down(touch):
            return True
        if touch.is_mouse_scrolling:
            return False
        if not self.collide_point(touch.x, touch.y):
            return False
        if self in touch.ud:
            return False
        touch.grab(self)
        touch.ud[self] = True
        self.dispatch('on_drag', touch)
        return True

    def on_touch_move(self, touch):
        if touch.grab_current is self:
            self.dispatch('on_drag', touch)
            return True
        if super(PhysicsObject, self).on_touch_move(touch):
            return True
        return self in touch.ud

    def on_touch_up(self, touch):
        if touch.grab_current is not self:
            return super(PhysicsObject, self).on_touch_up(touch)
        self.dispatch('on_drag', touch)
        touch.ungrab(self)
        return True
コード例 #35
0
ファイル: test_properties.py プロジェクト: Coffelius/kivy
    def test_numericcheck(self):
        from kivy.properties import NumericProperty

        a = NumericProperty(0)
        a.link(wid, 'a')
        a.link_deps(wid, 'a')
        self.assertEqual(a.get(wid), 0)
        a.set(wid, 99)
        self.assertEqual(a.get(wid), 99)

        try:
            a.set(wid, '') # string shouldn't be accepted
            self.fail('number accept string, fail.')
        except ValueError:
            pass
コード例 #36
0
class MDDatePicker(FloatLayout, ThemableBehavior, ElevationBehavior,
                   ModalView):
    _sel_day_widget = ObjectProperty()
    cal_list = None
    cal_layout = ObjectProperty()
    sel_year = NumericProperty()
    sel_month = NumericProperty()
    sel_day = NumericProperty()
    day = NumericProperty()
    month = NumericProperty()
    year = NumericProperty()
    today = date.today()
    callback = ObjectProperty()

    class SetDateError(Exception):
        pass

    def __init__(self,
                 callback,
                 year=None,
                 month=None,
                 day=None,
                 firstweekday=0,
                 **kwargs):
        self.callback = callback
        self.cal = calendar.Calendar(firstweekday)
        self.sel_year = year if year else self.today.year
        self.sel_month = month if month else self.today.month
        self.sel_day = day if day else self.today.day
        self.month = self.sel_month
        self.year = self.sel_year
        self.day = self.sel_day
        super(MDDatePicker, self).__init__(**kwargs)
        self.selector = DaySelector(parent=self)
        self.generate_cal_widgets()
        self.update_cal_matrix(self.sel_year, self.sel_month)
        self.set_month_day(self.sel_day)
        self.selector.update()

    def ok_click(self):
        self.callback(date(self.sel_year, self.sel_month, self.sel_day))
        self.dismiss()

    def fmt_lbl_date(self, year, month, day, orientation):
        d = datetime.date(int(year), int(month), int(day))
        separator = '\n' if orientation == 'landscape' else ' '
        return d.strftime('%a,').capitalize() + separator + d.strftime(
            '%b').capitalize() + ' ' + str(day).lstrip('0')

    def set_date(self, year, month, day):
        try:
            date(year, month, day)
        except Exception as e:
            print(e)
            if str(e) == "day is out of range for month":
                raise self.SetDateError(
                    " Day %s day is out of range for month %s" % (day, month))
            elif str(e) == "month must be in 1..12":
                raise self.SetDateError(
                    "Month must be between 1 and 12, got %s" % month)
            elif str(e) == "year is out of range":
                raise self.SetDateError(
                    "Year must be between %s and %s, got %s" %
                    (datetime.MINYEAR, datetime.MAXYEAR, year))
        else:
            self.sel_year = year
            self.sel_month = month
            self.sel_day = day
            self.month = self.sel_month
            self.year = self.sel_year
            self.day = self.sel_day
            self.update_cal_matrix(self.sel_year, self.sel_month)
            self.set_month_day(self.sel_day)
            self.selector.update()

    def set_selected_widget(self, widget):
        if self._sel_day_widget:
            self._sel_day_widget.is_selected = False
        widget.is_selected = True
        self.sel_month = int(self.month)
        self.sel_year = int(self.year)
        self.sel_day = int(widget.text)
        self._sel_day_widget = widget
        self.selector.set_widget(widget)

    def set_month_day(self, day):
        for idx in range(len(self.cal_list)):
            if str(day) == str(self.cal_list[idx].text):
                self._sel_day_widget = self.cal_list[idx]
                self.sel_day = int(self.cal_list[idx].text)
                if self._sel_day_widget:
                    self._sel_day_widget.is_selected = False
                self._sel_day_widget = self.cal_list[idx]
                self.cal_list[idx].is_selected = True
                self.selector.set_widget(self.cal_list[idx])

    def update_cal_matrix(self, year, month):
        try:
            dates = [x for x in self.cal.itermonthdates(year, month)]
        except ValueError as e:
            if str(e) == "year is out of range":
                pass
        else:
            self.year = year
            self.month = month
            for idx in range(len(self.cal_list)):
                if idx >= len(dates) or dates[idx].month != month:
                    self.cal_list[idx].disabled = True
                    self.cal_list[idx].text = ''
                else:
                    self.cal_list[idx].disabled = False
                    self.cal_list[idx].text = str(dates[idx].day)
                    self.cal_list[idx].is_today = dates[idx] == self.today
            self.selector.update()

    def generate_cal_widgets(self):
        cal_list = []
        for i in calendar.day_abbr:
            self.cal_layout.add_widget(WeekdayLabel(text=i[0].upper()))
        for i in range(6 * 7):  # 6 weeks, 7 days a week
            db = DayButton(owner=self)
            cal_list.append(db)
            self.cal_layout.add_widget(db)
        self.cal_list = cal_list

    def change_month(self, operation):
        op = 1 if operation is 'next' else -1
        sl, sy = self.month, self.year
        m = 12 if sl + op == 0 else 1 if sl + op == 13 else sl + op
        y = sy - 1 if sl + op == 0 else sy + 1 if sl + op == 13 else sy
        self.update_cal_matrix(y, m)
コード例 #37
0
ファイル: main.py プロジェクト: yihuang/kivent
class YourAppNameApp(App):
    count = NumericProperty(0)
コード例 #38
0
class AnalogeGauge(Widget):
    '''
    Gauge class

    '''
    unit = NumericProperty(1.8)
    size_text = NumericProperty(10)
    value = BoundedNumericProperty(0, min_value=0, max_value=100, errorvalue=0)
    start_angle = BoundedNumericProperty(90,
                                         min_value=-360,
                                         max_value=360,
                                         errorvalue=0)
    angle_width = BoundedNumericProperty(180,
                                         min_value=0,
                                         max_value=360,
                                         errorvalue=0)
    min_value = NumericProperty(0)
    max_value = NumericProperty(100)
    rotate_clock = BooleanProperty(True)
    file_background = StringProperty("cadran.png")
    file_gauge = StringProperty("")
    file_needle = StringProperty("")

    half_widget_view = BooleanProperty(False)

    padding = BoundedNumericProperty(10,
                                     min_value=0,
                                     max_value=360,
                                     errorvalue=0)

    mark_count = BoundedNumericProperty(10,
                                        min_value=0,
                                        max_value=360,
                                        errorvalue=0)
    mark_sub_count = BoundedNumericProperty(10,
                                            min_value=0,
                                            max_value=100,
                                            errorvalue=0)
    show_middle_marks = BooleanProperty(True)
    show_sub_marks = BooleanProperty(True)
    mark_size = BoundedNumericProperty(20,
                                       min_value=0,
                                       max_value=300,
                                       errorvalue=0)
    mark_mid_size = BoundedNumericProperty(15,
                                           min_value=0,
                                           max_value=300,
                                           errorvalue=0)
    mark_sub_size = BoundedNumericProperty(10,
                                           min_value=0,
                                           max_value=300,
                                           errorvalue=0)

    mark_color = ColorProperty('#ffffffff')
    mark_sub_color = ColorProperty('#ffffffff')
    mark_mid_color = ColorProperty('#ffffffff')

    needle_color = ColorProperty('#ff0000ff')
    glab_color = ColorProperty('#ff0000ff')

    def __init__(self, **kwargs):
        super(AnalogeGauge, self).__init__(**kwargs)
        self._gauge_widget = Widget()
        self._gauge = self._gauge_widget

        self._needle_widget_safe = Widget()
        self._needle_widget = self._needle_widget_safe

        self._form_processor_constants()

        self._needle = Scatter(size=self.size,
                               do_rotation=False,
                               do_scale=False)

        self._background_widget = Widget()
        self._background = Scatter(size=self.size,
                                   do_rotation=False,
                                   do_scale=False)

        self._glab = Label(font_size=self.size_text,
                           markup=True,
                           font_name='digital')

        self._needle.add_widget(self._needle_widget)

        self.add_widget(self._background)
        self.add_widget(self._gauge)
        self.add_widget(self._glab)
        self.add_widget(self._needle)

        self.bind(pos=self._update)
        self.bind(size=self._update)
        self.bind(value=self._turn)

        self.bind(file_gauge=self._reform_widget_graphics)
        self.bind(file_needle=self._reform_widget_graphics)
        self.bind(file_background=self._reform_widget_graphics)

        self.bind(min_value=self._form_processor_constants)
        self.bind(rotate_clock=self._form_processor_constants)
        self.bind(max_value=self._form_processor_constants)
        self.bind(start_angle=self._form_processor_constants)
        self.bind(angle_width=self._form_processor_constants)

        self.bind(mark_color=self._create_gaudge)
        self.bind(mark_sub_color=self._create_gaudge)
        self.bind(mark_mid_color=self._create_gaudge)
        self.bind(show_middle_marks=self._create_gaudge)
        self.bind(show_middle_marks=self._create_gaudge)
        self.bind(mark_count=self._create_gaudge)
        self.bind(mark_sub_count=self._create_gaudge)

        self.bind(needle_color=self._create_needle)

        self.bind(padding=self._update)

        self._update()
        self._reform_widget_graphics()
        self._turn()

    def _form_processor_constants(self, *args):
        self.property('value').set_min(self, self.min_value)
        self.property('value').set_max(self, self.max_value)
        self.unit = self.angle_width / abs(self.max_value - self.min_value) * (
            -1 if self.rotate_clock else 1)
        #print(self.unit, self.angle_width)

    def _reform_widget_graphics(self, *args):
        #print(self.size)

        if self.file_gauge:
            self.remove_widget(self._gauge)
            self._gauge = get_module_resource_path(self.file_gauge,
                                                   size=self.size,
                                                   resource_package=__name__)
            self.add_widget(self._gauge)
        else:
            self.remove_widget(self._gauge)
            self._gauge = self._gauge_widget
            self.add_widget(self._gauge)

        if self.file_background:
            self._background.remove_widget(self._background_widget)
            self._background_widget = get_module_resource_path(
                self.file_background,
                size=self.size,
                resource_package=__name__)
            self._background.add_widget(self._background_widget)

        if self.file_needle:
            self._needle.remove_widget(self._needle_widget)
            self._needle_widget = get_module_resource_path(
                self.file_needle, size=self.size, resource_package=__name__)
            self._needle.add_widget(self._needle_widget)
        else:
            self._needle.remove_widget(self._needle_widget)
            self._needle_widget = self._needle_widget_safe
            self._needle.add_widget(self._needle_widget)

    def _turn(self, *args):
        '''
        Turn needle, 1 degree = 1 unit, 0 degree point start on 50 value.

        '''
        self._needle.center_x = self._gauge.center_x
        self._needle.center_y = self._gauge.center_y
        self._needle.rotation = self.start_angle + (self.value -
                                                    self.min_value) * self.unit
        #print(self.start_angle, self.unit,self.value,self.min_value,self._needle.rotation)
        self._glab.text = "[b]{0:.0f}[/b]".format(self.value)

    def _create_needle(self, *args):
        if self._needle_widget == self._needle_widget_safe:
            self._needle_widget_safe.canvas.clear()
            with self._needle_widget_safe.canvas:
                Color(*self.needle_color)
                Line(points=(*self._needle_widget_safe.center,
                             self._needle_widget_safe.center_x,
                             self._needle_widget_safe.center_y +
                             self.circle_radius))
                Line(points=(*self._needle_widget_safe.center,
                             self._needle_widget_safe.center_x,
                             self._needle_widget_safe.center_y +
                             self.circle_radius - 20),
                     width=1.5)
                Ellipse(pos=(self._needle_widget_safe.center_x - 5,
                             self._needle_widget_safe.center_y - 5),
                        size=(10, 10))

    def _create_gaudge(self, *args):
        if self._gauge == self._gauge_widget:

            self._gauge_widget.canvas.clear()
            if self.mark_count > 0:
                delta_mark = self.angle_width / self.mark_count
                mark_width = 10
                mark_end = min(self.width, self.height) / 2
                with self._gauge_widget.canvas:

                    if self.show_sub_marks:
                        Color(*self.mark_sub_color)
                        sub_delta_mark = delta_mark / self.mark_sub_count
                        count = self.mark_count * self.mark_sub_count + 1
                        sub_start_size = self.circle_radius - self.mark_sub_size
                        for i in range(count):
                            Line(points=get_mark_vector(
                                *self.circle_pos, sub_start_size,
                                self.mark_sub_size, self.start_angle -
                                sub_delta_mark * i))

                    if self.show_middle_marks:
                        Color(*self.mark_mid_color)
                        sub_delta_mark = delta_mark / 2
                        count = self.mark_count * 2 + 1
                        sub_start_size = self.circle_radius - self.mark_mid_size
                        for i in range(count):
                            Line(points=get_mark_vector(
                                *self.circle_pos, sub_start_size,
                                self.mark_mid_size, self.start_angle -
                                sub_delta_mark * i))

                    Color(*self.mark_color)
                    start_size = self.circle_radius - self.mark_size
                    for i in range(self.mark_count + 1):
                        Line(points=get_mark_vector(
                            *self.circle_pos, start_size, self.mark_size,
                            self.start_angle - delta_mark * i))

    def _update(self, *args):
        '''
        Update gauge and needle positions after sizing or positioning.

        '''
        if self.half_widget_view:
            self.circle_radius = min(*self.size) - self.padding * 2
            self.circle_size = (self.circle_radius, self.circle_radius)
            self.circle_pos = (self.center_x,
                               self.center_y - self.circle_radius / 2)
            self._bg_pos = (self.x, self.y - self.circle_radius / 2)
        else:
            self.circle_radius = min(*self.size) / 2 - self.padding
            self.circle_size = (self.circle_radius, self.circle_radius)
            self.circle_pos = self.center
            self._bg_pos = (self.x, self.y)

        self._needle.size = self.size
        self._gauge.size = self.size
        self._gauge.pos = self.pos
        self._gauge.center = self.circle_pos

        self._needle.pos = (self.x, self.y)
        self._needle.center = self.circle_pos

        self._background.pos = self._bg_pos

        self._needle_widget.size = self.size
        self._background_widget.size = self.size

        self._glab.center_x = self._gauge.center_x
        self._glab.center_y = self.center_y + (self.height / 4)

        self._create_gaudge()
        self._create_needle()

    def set_animate(self, value, easing='in_out_quad', speed=1):
        from kivy.animation import Animation
        Animation(value=value, duration=speed, t=easing).start(self)